




C++调用C函数报“undefined reference”是因为名称修饰导致符号不匹配,需用extern "C"声明;必须作用于C++头文件声明处,且链接时库参数要放在目标文件之后。
因为C++编译器默认对函数名做name mangling(名称修饰),比如void foo(int)可能被编译成_Z3fooi;而C编译器只保留foo。链接时,C++代码找的是修饰后的符号,但C库提供的是未修饰的符号,自然找不到。
根本原因不是语法错误,是ABI层面的符号不匹配。只要看到类似undefined reference to 'xxx'且确认函数确实存在于C库中,第一反应就该检查extern "C"是否漏了。
常见误区:只在C源文件里写extern "C",或只在C++调用代码里包一层——都没用。它必须作用于C++编译器“看到的声明”,也就是C++代码包含的头文件中。
mylib.h,应在其中用条件宏包裹:#ifdef __cplusplus
extern "C" {
#endif
void c_func(int x);
#ifdef __cplusplus
}
#endifextern "C" {
#include "mylib.h"
}.cpp里写extern "C" { void c_func(int); }——万一多个文件都调用,重复声明易出错,且无法保证一致性ld链接器是单向扫描,遇到未解析符号就记下来,后续遇到定义才填充。如果把-lmylib放最前面,链接器还没看到你的main.o里的调用,就跳过了库里的符号。
g++ main.cpp -o app -L./lib -lmylib
g++ -L./lib -lmylib main.cpp -o app(此时main.o尚未参与链接,-lmylib被忽略)-lm),也要放在-lmylib之后,因为依赖关系是传递的extern "C"只影响

struct、enum、#define的处理一致,可直接共用头文件。
但有三个实际坑点:
enum class是强类型,不能和C的普通enum混用,传参时需显式static_cast
#pragma pack(1),C++代码也得同步加,否则sizeof不同、内存布局错位"hello"类型是char[6],C++中是const char[6],传给期望char*的C函数时,编译器会报deprecated conversion警告,需用const_cast(仅当C函数确实不修改内容时)真正容易被忽略的是:extern "C"不解决运行时行为差异,比如C库用malloc分配内存,C++代码不能用delete释放——跨语言内存管理必须严格遵循原语言约定。