c++ - 如何调用具有多个不同签名的函数(如 glibc 调用 main)?

标签 c++ gcc linker glibc

C++ 标准表明 main 可以有 two possible signatures

int main()               // (1)
int main(int, char*[])   // (2)

此外,main() 通常从__libc_start_main 调用,它定义在glibc 源码的csu/libc-start.c 中代码。下面复制了此函数中 main 的调用。

result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);

我们观察到这里的调用使用了三个参数,这似乎没有产生任何链接器错误,尽管签名与上述两种形式都不匹配。


我正在编写一个定义 main() 的线程库,并希望应用程序能够定义以下两个函数之一。

int AppMain()               // (1)
int AppMain(int, char*[])   // (2)

不幸的是,如果我使用上面的第二种形式声明 AppMain 并从我的库的 main 中调用它,而应用程序使用第一种形式,那么我会得到一个 Unresolved 问题引用链接器错误,表明我调用的函数不存在。

因为相对于 main 这对于 glibc 来说似乎不是问题,我怎样才能以一种避免链接器错误?


这是重现问题的简单方法。

生成文件

CCFLAGS=-Wall -Werror

all: libLib.a App

libLib.a: Lib.o
    ar rcs $@ $^

App: App.o libLib.a
    g++ -o $@ $< -L. -lLib

%.o: %.cc
    g++ $(CCFLAGS)  -O3 $(LIBS) -fPIC -c  -o $@ $<

库.cc

#include <stdio.h>

int AppMain(int argc, char** argv);

#undef main
int main(int argc, char** argv){
    printf("Hello World\n");    
    AppMain(argc, argv);
}

App.cc(工作版)

#include <stdio.h>

int AppMain(int argc, char** argv){
    printf("Application says Hello world\n");
    return 0;
}

App.cc(非工作版)

#include <stdio.h>

int AppMain(){
    printf("Application says Hello world\n");
    return 0;
}

在第二个版本下,这里是链接器错误。

./libLib.a(Lib.o): In function `main':
Lib.cc:(.text.startup+0x24): undefined reference to `AppMain(int, char**)'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'App' failed
make: *** [App] Error 1

最佳答案

不管有什么不同的建议,我只是回答你的问题

how might I write my invocation or declaration in a way that avoids the linker error?

你可以在App.cc中写下你的定义

extern "C" int AppMain()
{
    …

你在Lib.cc中的声明为

extern "C" int AppMain(int argc, char** argv);

避免name mangling ,与 glibc 中最有可能完成的操作相同。可能在某些 C++ 编译器中这不起作用,但它肯定适用于 GCC。

关于c++ - 如何调用具有多个不同签名的函数(如 glibc 调用 main)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41197849/

相关文章:

c - 将外部静态库的段放置到特定位置

c++ - 我可以为 2 个或更多应用程序进行 QSettings 设置吗?

C++类实例数组初始化

c++ - 如何在应用程序容器内启动应用程序?

gcc - Spin:错误,生成此 pan.c 的 spin 版本采用了不同的字长 (4 iso 8)

gcc - 如何使 "Locals and Expressions"调试窗口与 gcc 4.8 一起运行?

c - 读取寄存器值到变量,用一个 asm 命令

c++ - 如何为 const std::vector<unsigned char> 释放内存

visual-c++ - 如何清除链接警告4099

multithreading - 只有 dlmopen 而不是 dlopen 的未解析符号