C++调用C函数时g++链接阶段出现未定义引用及重复定义问题
嘿,这俩问题都是C/C++混合编程里的经典坑,完全不用重写你的C代码就能搞定,听我给你拆解:
一、Undefined Reference错误:名字修饰不匹配
C++为了支持函数重载,会对函数名做名字修饰(Name Mangling),比如把void foo(int)改成类似_Z3fooi的符号;但C语言不会搞这套,你的chorusclient.c编译出来的函数符号就是原名字。
所以C编译器在链接时,会去找修饰后的符号,自然找不到C代码里的原始符号,就报“未定义引用”了。解决方法很简单:让C编译器知道哪些函数是C风格的。
两种实现方式:
在C++代码里包裹头文件:
在你的chorusmain.cpp里,把包含chorusclient.h的代码改成这样:extern "C" { #include "chorusclient.h" }这样C++就会按照C的规则处理这个头文件里的所有函数声明。
在C头文件里加条件编译(更通用):
修改chorusclient.h,在开头和结尾加上这段:#ifdef __cplusplus extern "C" { #endif // 这里保留原来的函数声明、结构体定义等内容 #ifdef __cplusplus } #endif这样不管是C还是C编译器包含这个头文件,都会自动适配,以后其他C文件用这个头文件也不用再改了。
二、multiple references to svrport错误:变量重复定义
这个错误说明svrport这个变量在链接时被找到了多个定义,常见原因有两个:
情况1:头文件里直接定义了变量
如果你的chorusclient.h里写了类似int svrport;这样的代码,那每个包含这个头文件的源文件(比如chorusmain.cpp和chorusclient.c)都会生成一个svrport的定义,链接时就冲突了。
解决方法:
- 在
chorusclient.h里只做声明:extern int svrport; - 然后在
chorusclient.c里真正定义这个变量:int svrport;(比如在文件开头或者合适的位置)
情况2:编译/链接时重复加入了目标文件
检查你的编译命令,比如如果用g++编译,是不是写成了:
g++ chorusmain.cpp chorusclient.c chorusclient.c -o chorus_app
这里重复写了chorusclient.c,导致编译出两个相同的目标文件,链接时就会出现重复定义。或者Makefile里有没有重复添加chorusclient.o的情况,修正一下编译命令即可。
按照上面的步骤来,应该就能解决这两个问题啦!
内容的提问来源于stack exchange,提问作者skmansfield

