链接自制C存根库时出现Undefined reference问题求助
结合你描述的现象,这大概率是C/C++跨语言链接的典型问题,我整理了几个最可能的原因和对应的解决办法:
1. 缺少C语言符号的兼容性声明(最常见原因)
你的库是C语言编写的,但链接的是C代码——C编译器会对函数名做名字修饰(Name Mangling),而C语言的函数符号是原始名称。如果头文件myLib.h里没告诉C++编译器这是C语言函数,编译foo.cpp时生成的目标文件会去找修饰后的符号,自然和库中的C风格符号匹配不上。
解决方法:
修改myLib.h,用条件编译包裹所有函数声明,确保C++编译器以C语言规则处理这些符号:
#ifndef MYLIB_H #define MYLIB_H #ifdef __cplusplus extern "C" { #endif // 这里放你的所有函数声明,比如: void my_func(); int my_other_func(int arg); #ifdef __cplusplus } #endif #endif // MYLIB_H
修改后重新编译存根库,再重新编译链接foo.cpp。
2. 链接命令的顺序错误
ld(或g++/clang++)处理链接时,会按从左到右的顺序解析符号。如果把库放在目标文件前面,比如:
g++ -lmyLib foo.o -o foo
链接器会先处理libmyLib,此时还没看到foo.o里的符号引用,会认为库中的函数都没被用到,直接跳过;之后处理foo.o时,发现需要的符号找不到,就会报Undefined reference。
解决方法:
把库放在目标文件之后:
g++ foo.o -lmyLib -o foo
3. 验证库中的符号是否正确
你可以用nm命令查看库中的符号是否是C风格的(没有C++的修饰前缀,比如__Z开头的名字):
- 对于静态库:
正常的C函数符号应该是nm libmyLib.aT类型(文本段,即函数实现),比如T my_func。 - 对于动态库:
同样应该看到没有修饰的函数名。nm -D libmyLib.so
如果看到类似_Z7my_funcv这样的名字,说明你的库被当成C++编译了,要检查库的Makefile,确保用gcc而不是g++编译C源文件。
4. 检查ld警告的具体内容
你提到ld -lmyLib --verbose有警告,比如可能是库的架构不匹配(比如代码是64位,库是32位,反之亦然),或者库没有设置SONAME(这个一般不影响链接,但可能影响运行时)。如果前面的方法都没解决,可以把警告内容贴出来进一步排查。
内容的提问来源于stack exchange,提问作者ben23f

