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

时间:2016-12-17 10:59:16

标签: c++ gcc linker glibc

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

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

此外,main()通常是从__libc_start_main调用的,csu/libc-start.cglibc源代码的main中定义。此函数内的result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); 调用将复制到下面。

main()

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

我正在编写一个定义int AppMain() // (1) int AppMain(int, char*[]) // (2) 的线程库,并希望应用程序能够定义以下两个函数之一。

AppMain

不幸的是,如果我使用上面的第二个表单声明main并从我的库glibc调用它,并且应用程序使用第一个表单,那么我得到一个未解析的引用链接器表示我调用的函数不存在的错误。

因为mainCCFLAGS=-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 $@ $< 来说似乎不是问题,如何以避免链接器错误的方式编写我的调用或声明?

这是一种重现问题的简便方法。

生成文件

#include <stdio.h>

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

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

Lib.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;
}

App.cc(非工作版)

./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

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

SELECT a.id, a.user_id, a.tc1, a.tc4, a.tc2, b.avatar, c.username, 
    (select rank from (SELECT 
        IF (@score=s.tc5, @rank:=@rank, @rank:=@rank+1) rank,
        @score:=s.tc5 tc5s
        FROM treningove_casy s,
        (SELECT @score:=0, @rank:=0) r
        ORDER BY tc5 DESC) s ) as rank
FROM 
treningove_casy a INNER JOIN  
sn_users b ON a.user_id=b.id INNER JOIN
users c ON a.user_id=c.id , (SELECT @curRank := 0) r
WHERE  a.tc2 LIKE  'Motokáry Modrice' 
GROUP BY a.user_id

1 个答案:

答案 0 :(得分:0)

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

  

如何避免链接程序错误来编写调用或声明?

您可以在App.cc中将定义写为

extern "C" int AppMain()
{
    …

,您在Lib.cc中的声明为

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

避免使用name mangling,这与最可能在glibc中执行的操作相同。可能有些C ++编译器无法执行此操作,但肯定可以与GCC一起使用。