如何在Makefile中添加.c、.cc、.so生成新.so?及包装器未定义引用解决建议
我来帮你一步步解决这两个问题——先搞定undefined reference错误,再教你写Makefile生成新的动态库。
一、解决"undefined reference to the library"错误
这个问题通常和C/C++名字修饰规则、编译链接选项或库依赖顺序有关,咱们挨个排查:
1. 先确认包装器的extern "C"声明
C和C的函数名修饰规则完全不同,如果你的wr.h里没加extern "C",C代码调用时会找不到C编译出来的符号。正确的wr.h写法应该是:
#ifdef __cplusplus extern "C" { #endif // 这里放你的包装函数声明,比如: void my_cpp_lib_wrapper(); #ifdef __cplusplus } #endif
这样不管是C还是C++编译器处理这个头文件,都会生成C风格的函数名,C代码就能正确识别了。
2. 检查编译链接选项
编译C代码(wr.cc)必须用g++,而且要加-fPIC生成位置无关代码(动态库必需);链接生成.so时,要确保把依赖的原C库也链接进去。
比如单独执行的编译链接命令应该是:
# 编译wr.cc为目标文件 g++ -c -fPIC wr.cc -o wr.o # 链接生成libwr.so,假设原C++库叫libfoo.so,放在当前目录就加-L./ g++ -shared -o libwr.so wr.o -L./ -lfoo
3. 排查测试程序的链接
编译test.c时,要指定动态库的路径(-L./)和库名(-lwr),而且链接顺序要注意:被依赖的库要放在后面。比如:
gcc test.c -o test -L./ -lwr # 运行前临时设置环境变量,让系统找到本地的.so export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH ./test
4. 验证动态库中的符号
如果还是有问题,用nm -D libwr.so查看动态库导出的符号,确认你的包装函数是C风格的名字(没有_Z开头的C++修饰符)。
二、在Makefile中组合.c、.cc、.so生成新的.so
我给你写一个完整的Makefile示例,包含生成libwr.so、测试程序,以及生成新动态库(比如libcombined.so)的逻辑:
# 定义编译器和编译选项 CC = gcc CXX = g++ # 编译选项:开启警告,生成位置无关代码 CFLAGS = -Wall -fPIC CXXFLAGS = -Wall -fPIC # 链接动态库的选项 LDFLAGS = -shared # 依赖的原C++库,比如libfoo.so,如果不需要可以去掉 LIBS = -lfoo # 目标1:生成包装器动态库libwr.so libwr.so: wr.o $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) wr.o: wr.cc wr.h $(CXX) $(CXXFLAGS) -c -o $@ $< # 目标2:编译测试程序test test: test.c libwr.so $(CC) -o $@ $< -L./ -lwr @echo "运行测试程序:" @export LD_LIBRARY_PATH=./:$${LD_LIBRARY_PATH} && ./test # 目标3:生成新的动态库libcombined.so,组合test.c、wr.cc和依赖库 libcombined.so: test.o wr.o $(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) test.o: test.c wr.h $(CC) $(CFLAGS) -c -o $@ $< # 清理目标 clean: rm -f *.o *.so test
关键说明:
- 所有生成动态库的目标文件(
.o)都必须用-fPIC编译,否则无法生成动态库。 - 链接包含C代码的动态库时,要用
g++而不是gcc,因为g++会自动链接C标准库。 - 如果新
.so需要依赖现有的libwr.so,可以修改libcombined.so的规则:libcombined.so: test.o libwr.so $(CXX) $(LDFLAGS) -o $@ test.o -L./ -lwr $(LIBS)
按照上面的步骤排查和修改,应该能解决你的问题。如果还有具体的错误日志,可以贴出来,我再帮你细化排查。
内容的提问来源于stack exchange,提问作者user1322133
相关产品推荐
相关产品推荐

