【问题标题】:C99: Call main function from another 'main'?C99:从另一个“主”调用主函数?
【发布时间】:2015-10-09 17:59:58
【问题描述】:

这个question 有一个相似的标题,但我们正在讨论不同的事情。

假设我想调用代码 foo.c 的main

int main(){
   ...
}

问题是调用者是另一个main 例程,似乎不可能有两个main 函数。

如何从另一个main 调用foo.c 的主函数?

foo.c 中main 的名称无法更改,因为它不是用户代码。

【问题讨论】:

  • 为什么有两个主要功能?
  • @Kay。是的,有点。我在上面编辑了我的问题。无法在 foo.c 中更改名称“main”。
  • 嗯,在某个地方你应该有一个“crt.c”源文件,其中包含设置 C 运行时环境的代码 - 堆等,然后,在接近结尾的某个地方,跳转到或调用 main ()。如果您编辑 crt 以改为调用 myMain(),您应该能够重建 crt 和您的应用程序,以便 myMain() 被称为 C 入口点。然后,您可以随时调用另一个 main()。

标签: c main


【解决方案1】:

你所描述的情况听起来是这样的:

/**
 * bar.c
 */
...
int main( void )
{
  ...
  // call foo.c's main function directly
  main( );
  ...
}

/**
 * foo.c
 */
int main( void )
{
  ...
}

你不能那样做。没有办法构建一个定义了两个main 函数的程序。

所以问题就变成了,你到底想在这里做什么?

  1. bar.cfoo.c 是否应该被构建到 same 可执行文件中,bar.c 中的代码调用在 foo.c 中定义的代码,同时仍然允许构建 foo.c作为一个独立的程序?如果是这样,那么您将不得不将该代码从foo.cmain 函数中取出并将其放入一个单独的函数中,并且您将不得不使用一些预处理器魔法来抑制foo.c 的@987654331 @定义当两个文件一起构建时,如下所示:
    /**
     * bar.c
     */
    #include "foo.h"
    ...
    int main( void )
    {
      ...
      foo_func(); // function defined in foo.c
      ...
    }
    
    /**
     * foo.h
     */
    #ifndef FOO_H
    #define FOO_H
    
    void foo_func( void );
    #endif
    
    /**
     * foo.c
     */
    #include "foo.h"
    
    void foo_func( void )
    {
      ...
    }
    
    #ifndef EXTERNAL_DRIVER
    int main( void )
    {
      ...
      foo_func();
      ...
    }
    #endif
    
    这使得 `foo` 可以作为独立程序构建,也可以作为更大程序的一部分。要将其构建为更大程序的一部分,您必须定义 `EXTERNAL_DRIVER` 宏,如下所示:
    gcc -o bar bar.c foo.c -DEXTERNAL_DRIVER
  2. bar.cfoo.c 是要构建到两个单独的可执行文件中,并让一个正在运行的 bar 实例启动一个新的 foo 实例,然后等待 foo 实例完成运行后再继续?如果是这样,那么您可以使用 C 标准库的 system 函数从 bar 调用 foo
    system("foo");
    尽管您可能必须将路径指定为命令的一部分,例如
    system("./foo")
    要么
    system("/some/absolute/path/name/foo");
    如果您在 *nix 系统上,则可以使用 forkexec* 函数之一的组合来做同样的事情,除了 bar 实例没有 em> 等待foo 完成执行。 如果您希望两个程序在运行时共享数据,那么您将不得不研究各种进程间通信技术(共享内存、套接字、管道等)。
  3. bar.cfoo.c 是否意味着构建到两个单独的可执行文件中,并且在运行中的 foo 实例中定义了运行中的 bar 实例执行代码?那是一个远程过程调用,在过去的 20 年中我可能做过一次,并且像进程间通信一样,对于 SO 答案有点涉及。

如果我没有涵盖您的特定用例,请告诉我。

【讨论】:

    【解决方案2】:

    您可以像这样重命名main() 函数:

    objcopy --redefine-sym main=that_other_main obj1.o obj2.o
    

    其中obj.o 包含您不想成为程序主入口点的main()。然后您可以使用that_other_main(argc, argv) 调用它。

    【讨论】:

      【解决方案3】:

      你不能使用两个主要函数。你最好将函数名从'main'更改为foo.c中的任何其他函数并调用它。我认为它不会改变你程序的最终结果。

      【讨论】:

      • 如果添加了新信息,请仅添加新答案。
      【解决方案4】:

      您可以做的最好的事情是使用“system('otherprog.exe arg1 arg2')" 调用来调用其他程序。也就是说,如果您不关心直接输出到标准输出的输出。

      如果您想捕获第二个程序的输出,则需要使用更复杂的 popen() 调用打开管道。

      FILE *fp;
      int status;
      char res[MAXLINE];
      
      
      fp = popen("otherprog.exe param1 parm2", "r");
      if (fp == NULL)
          /* Handle error */;
      
      while (fgets(res, MAXLINE, fp) != NULL) {
          /* capture each stdout line from otherprog.exe */
          printf("do something with %s", res);
      }
      
      status = pclose(fp);
      

      【讨论】:

        【解决方案5】:

        如何从另一个 main 调用 foo.c 的 main 函数?这里有一个约束。 foo.c 中的 main 名称不能更改,因为它不是用户代码。

        一个程序中不能有两个main 函数。

        您不能从另一个函数调用 foo.c 的 main,因为就用户代码而言,main 是程序的起点。

        只有通过两个不同的程序并使用 system 或任何 exec*** 系列函数从另一个程序执行包含 foo.c 的 main 的程序才能实现您想要完成的任务.

        【讨论】:

          【解决方案6】:

          而且似乎不可能有两个“主要”功能。

          在同一个对象(二进制、共享库)中不能有两个同名符号...

          在编译结束时,编译器将所有objects files 合并到您的目标中,按名称解析符号。如果您的两个mains 名称相同,则无法区分它们。

          重命名函数之一(不是程序真正入口点的函数)。

          编辑:如果你不能从代码中触摸到对方的主名,请在编译后更改它。以 gcc 为例:

          gcc -o other_main.o -c other_main.c
          objcopy --prefix-symbols=foo_ other_main.o
          gcc -o yourbinary other_main.o main.c
          

          然后,在你的 real main 中调用 foo_main 而不是 main

          【讨论】:

          • 没有。这是行不通的。真正的切入点来自我的程序。 foo.c 中的“main”是另一个人的程序,我无法触摸。
          • @zell 编辑了我的答案。
          • 谢谢。我今天会试试。你能解释一下“objcopy --prefix-symbols=foo_other_main.o”吗?
          【解决方案7】:

          在一个程序中不可能有两个主要的

          【讨论】:

            猜你喜欢
            • 2014-10-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-10-04
            • 1970-01-01
            相关资源
            最近更新 更多