You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言多文件编译多main()与init()函数按需加载实现问题

解决多C文件同名main函数调用冲突方案

核心解决思路是将script2.c、script3.c分别编译为独立的动态共享库,在script1.c中通过动态加载接口按需获取对应函数地址调用,完全规避符号冲突问题,且无需修改原有函数名称。

步骤1:修正代码语法并补充动态加载逻辑

script1.c 代码(新增动态加载逻辑)

#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char *argv[]) {
    printf("loaded main() in script1.c\n");
    void *handle2 = dlopen("./libscript2.so", RTLD_LAZY);
    void *handle3 = dlopen("./libscript3.so", RTLD_LAZY);
    
    // 定义对应函数指针类型
    typedef int (*main_func)(int, char**);
    typedef void (*init_func)(int, char**);
    
    // 调用script2的main
    main_func main2 = dlsym(handle2, "main");
    int ret = main2(argc, argv);
    if (ret == 0) {
        // 调用script3的init
        init_func init3 = dlsym(handle3, "init");
        init3(argc, argv);
        // 两次调用script3的main
        main_func main3 = dlsym(handle3, "main");
        ret = main3(argc, argv);
        if (ret == 0) {
            ret = main3(argc, argv);
        }
    }
    // 关闭动态库句柄
    dlclose(handle2);
    dlclose(handle3);
    return ret;
}

script2.c 补充必要头文件

#include <stdio.h>
int main(int argc, char *argv[]) {
  printf("loaded main() in script2.c\n");
  return 0;
}

script3.c 补充必要头文件(省略逻辑保留原有函数名)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void init(int argc, char *argv[]) {
  argv[0] = (char*)strdup("OK");
  printf("loaded init() in script3.c\n");
}

int main(int argc, char *argv[]) {
  if(strcmp(argv[0], "OK") == 0) {
    printf("loaded main() in script3.c\n");
  }
  return 0;
}

步骤2:执行编译命令

  1. 编译script2为动态库:
    gcc -fPIC -shared -o libscript2.so script2.c
  2. 编译script3为动态库:
    gcc -fPIC -shared -o libscript3.so script3.c
  3. 编译主程序script1,链接动态加载库dl:
    gcc -o script1 script1.c -ldl

步骤3:运行验证

执行./script1即可得到期望输出:

loaded main() in script1.c
loaded main() in script2.c
loaded init() in script3.c
loaded main() in script3.c
loaded main() in script3.c

原方案失效原因说明

  • 静态链接允许多重定义的方案:同一全局符号只会保留最先加载的实例,无法区分不同文件的同名main函数,还会出现递归调用死循环。
  • exec/system调用方案:启动独立进程默认从目标程序的main函数开始执行,无法控制先调用init函数再执行main。
  • constructor属性方案:构造函数会在动态库加载时自动执行,无法做到按需调用,会出现额外的触发次数。

内容的提问来源于stack exchange,提问作者Kryk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 23:27:07