我正在尝试将一个小的C ++测试程序main.o
链接到第三方静态库,但得到一些莫名其妙的undefined reference
错误。
特别:
g++ -o secoTest -lpthread main.o libEAPI.a
main.o: In function `main':
main.cpp:(.text+0x29fe): undefined reference to `EApiWDog_SetConfigAndStart(unsigned int, unsigned int, unsigned int, unsigned int, unsigned char, unsigned char, unsigned char)'
main.cpp:(.text+0x33fc): undefined reference to `EApiSetCarrier(unsigned char)'
main.o:main.cpp:(.text+0x3956): more undefined references to `EApiSetCarrier(unsigned char)' follow
main.o: In function `main':
main.cpp:(.text+0x3965): undefined reference to `EApiGPIOGetSerialCfg(unsigned char*)'
main.cpp:(.text+0x3a0a): undefined reference to `EApiSetCarrier(unsigned char)'
main.cpp:(.text+0x3a19): undefined reference to `EApiGPIOSetSerialCfg(unsigned char)'
main.cpp:(.text+0x3adf): undefined reference to `EApiFanEnable(unsigned int, unsigned char)'
main.cpp:(.text+0x3b83): undefined reference to `EApiFanDisable()'
collect2: ld returned 1 exit status
但是,似乎符号存在于库中。例如:
nm --demangle libEAPI.a | grep EApiFanDisable
00003c20 T EApiFanDisable
奇怪的是符号并不完全相同。在main.o
它是
nm --demangle main.o | grep EApiFanDisable
U EApiFanDisable()
所以有一个有()
,有一个没有。
同样的,
nm --demangle main.o | grep EApiSetCarrier
U EApiSetCarrier(unsigned char)
nm --demangle libEAPI.a | grep EApiSetCarrier
000015d0 T EApiSetCarrier
如果我从命令行中完全省略了库(例如,g++ -o secoTest -lpthread main.o
),它会按预期显示许多错误。
main.o
用()
引用外部符号[为什么?]:
U EApiVgaSetBacklightEnable
U EApiWDogStart
U EApiWDogTrigger
U EApiFanEnable(unsigned int, unsigned char)
U EApiFanDisable()
U EApiSetCarrier(unsigned char)
但是图书馆只有没有()
的符号[为什么?]:
000020e0 T EApiVgaSetBacklightEnable
000024e0 T EApiWDogStart
000026f0 T EApiWDogTrigger
00003c20 T EApiFanDisable
00003bf0 T EApiFanEnable
000015d0 T EApiSetCarrier
这是未定义引用的原因吗?我该如何解决?不确定下一步要去哪里......
(我无法修改第三方库,但有头文件。)
编辑
正如lisyarus所说,这里是没有nm
的--demangle
。实际上,符号是不同的。 g ++编译器(v4.4.7)只为某些符号生成一个受损的符号,而库总是有简单的符号... [为什么?]
nm libEAPI.a main.o | grep EApiWDogTrigger
000026f0 T EApiWDogTrigger
U EApiWDogTrigger
nm libEAPI.a main.o | grep EApiSetCarrier
000015d0 T EApiSetCarrier
U _Z14EApiSetCarrierh
库libEAPI.a
包含用C
编译的目标文件,而不是C++
。因此,符号没有被命名,并且不能用于解析由C ++代码生成的名称错误的函数引用。
跑:
nm libEAPI.a | grep EApiFanDisable
你会看到没有变化。
跑:
nm main.o | grep EApiFanDisable
并且你会看到被破坏的符号,既不是EApiFanDisable
也不是EApiFanDisable()
,而是更像_Z14EApiFanDisablev
,链接器实际上正试图解决。
为了避免这些链接错误,你必须通知你的C ++编译器,当它编译libEAPI
的头文件时,其中的声明具有外部C链接,因此它将发出对声明的符号的unmangled引用:如下所示:
main.cpp中
...
extern "C" {
#include "EAPI.h" // or whatever
}
...
顺便说一句,这个命令行:
g++ -o secoTest -lpthread main.o libEAPI.a
将无法链接基于Debian的发行版(Ubuntu等)上的libpthread
比Debian 6更新,因为从那时起所有库必须以依赖顺序链接:
g++ -o secoTest main.o libEAPI.a -lpthread
更好的是,不要使用非便携式-lpthread
并通过便携式选项-pthread
进行编译和链接。这意味着:做任何与Posix Threads支持编译/链接的权利