g++编译含C、CPP文件项目时调用C函数出现undefined reference错误
问题原因分析
- 核心问题是C和C混编的符号兼容问题:C编译器会对函数名做*名字修饰(Name Mangling)*以支持重载特性,而C编译器不会。你在C文件中直接引用C头文件的函数声明时,编译器会默认按照C的规则生成带修饰的函数符号,但是
jetsonGPIO.o是用C规则编译的,内部的函数符号没有修饰,二者无法匹配,就会出现undefined reference错误。 - 次要问题是Makefile缺失C源文件的显式编译规则:你当前的Makefile仅定义了
.cpp文件的编译规则,.c文件依赖make的隐含规则编译,可能存在编译参数不一致的隐患。
解决方案
第一步:修改C头文件添加extern "C"声明
在jetsonGPIO.h的首尾添加条件编译块,让C++编译器按照C的规则解析函数声明:
// jetsonGPIO.h 开头添加 #ifdef __cplusplus extern "C" { #endif // 原有头文件的全部内容,包括gpioExport、gpioSetDirection等函数的声明 // jetsonGPIO.h 结尾添加 #ifdef __cplusplus } #endif
第二步:补充Makefile的C文件编译规则
在Makefile中原有.cpp编译规则的下方,新增.c文件的编译规则:
%.o: %.cpp $(INCS) Makefile @echo $(CFLAGS) $(CXX) -c -o $@ $(CFLAGS) $< # 新增C文件编译规则 %.o: %.c $(INCS) Makefile @echo $(CFLAGS) $(CC) -c -o $@ $(CFLAGS) $<
验证修复效果
执行make clean && make重新编译即可解决链接错误。如果仍有问题,可以通过nm命令验证符号匹配情况:
- 查看C目标文件的导出符号:
nm jetsonGPIO.o | grep gpioExport,正常输出应为T gpioExport(无多余修饰字符) - 查看CPP目标文件的引用符号:
nm gstdsexample.o | grep gpioExport,修复后也应该显示为U gpioExport(和C目标文件的符号完全一致)
内容的提问来源于stack exchange,提问作者batuman
相关产品推荐
相关产品推荐

