将 C++ 链接到静态库;未定义的引用错误
Linking C++ to static library; undefined reference errors
我正在尝试 link 一个小型 C++ 测试程序,main.o
到第 3 方静态库,但遇到一些无法解释的 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
这会是未定义引用的原因吗?我将如何解决它?不确定下一步要看哪里...
(我无法修改第 3 方库,但有头文件。)
编辑
正如 lisyarus 所建议的,这里是没有 --demangle
的 nm
。确实,符号不同。 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++
。
因此,这些符号不是 name-mangled,也不能用于
解析 C++ 生成的 name-mangled 函数引用
代码。
运行:
nm libEAPI.a | grep EApiFanDisable
你不会看到任何变化。
运行:
nm main.o | grep EApiFanDisable
你会看到错位的符号,它既不是 EApiFanDisable
也不是 EApiFanDisable()
但更像是 _Z14EApiFanDisablev
,linker 实际上正在尝试
解决。
为避免这些 linkage 错误,您必须通知您的 C++ 编译器,当它
编译 libEAPI
的头文件,其中的声明具有
外部 C linkage,因此它将发出对声明的符号的未损坏引用:像这样:
main.cpp
...
extern "C" {
#include "EAPI.h" // or whatever
}
...
顺便说一句,这个命令行:
g++ -o secoTest -lpthread main.o libEAPI.a
将无法在 Debian-based 发行版上 link libpthread
(Ubuntu 等)
比 Debian 6 更新,因为所有库都必须 link 从那时起按依赖顺序编辑:
g++ -o secoTest main.o libEAPI.a -lpthread
更好的是,不要使用 non-portable -lpthread
并通过便携式
编译选项 -pthread
和 linkage。意思是:随心所欲
compile/link Posix 线程支持
是对的
我正在尝试 link 一个小型 C++ 测试程序,main.o
到第 3 方静态库,但遇到一些无法解释的 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
这会是未定义引用的原因吗?我将如何解决它?不确定下一步要看哪里...
(我无法修改第 3 方库,但有头文件。)
编辑
正如 lisyarus 所建议的,这里是没有 --demangle
的 nm
。确实,符号不同。 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++
。
因此,这些符号不是 name-mangled,也不能用于
解析 C++ 生成的 name-mangled 函数引用
代码。
运行:
nm libEAPI.a | grep EApiFanDisable
你不会看到任何变化。
运行:
nm main.o | grep EApiFanDisable
你会看到错位的符号,它既不是 EApiFanDisable
也不是 EApiFanDisable()
但更像是 _Z14EApiFanDisablev
,linker 实际上正在尝试
解决。
为避免这些 linkage 错误,您必须通知您的 C++ 编译器,当它
编译 libEAPI
的头文件,其中的声明具有
外部 C linkage,因此它将发出对声明的符号的未损坏引用:像这样:
main.cpp
...
extern "C" {
#include "EAPI.h" // or whatever
}
...
顺便说一句,这个命令行:
g++ -o secoTest -lpthread main.o libEAPI.a
将无法在 Debian-based 发行版上 link libpthread
(Ubuntu 等)
比 Debian 6 更新,因为所有库都必须 link 从那时起按依赖顺序编辑:
g++ -o secoTest main.o libEAPI.a -lpthread
更好的是,不要使用 non-portable -lpthread
并通过便携式
编译选项 -pthread
和 linkage。意思是:随心所欲
compile/link Posix 线程支持