gcc链接多共享库遇未定义引用问题及编译咨询
问题解答
1. GCC编译参数理解是否正确?
你的理解基本准确,补充几个细节:
-L:给链接器添加库文件的搜索目录,优先级高于系统默认的库搜索路径-l:链接器会自动匹配前缀lib和后缀.so/.a,比如-llogwritter对应查找liblogwritter.so或liblogwritter.a-I:预处理阶段添加头文件搜索目录,逻辑和-L一致但针对头文件,正确-Wl:将紧跟的参数直接传递给链接器,比如-Wl,-rpath=./就是告诉链接器把当前目录加入运行时库搜索路径,正确
2. 导致当前错误的缺失知识
核心问题是C/C++的名字修饰(Name Mangling)不兼容:
- 用
gcc编译C代码生成的共享库中,函数名保持原始的C风格(比如logWritter) - 但用
g++编译C++代码时,会对函数名进行特殊修饰(比如把logWritter(char const*)转换成_Z11logWritterPKc这类符号) - 链接阶段,C++目标文件会查找修饰后的符号,而你的C库提供的是未修饰的C符号,因此出现
undefined reference错误
另外,编译命令里-I./的位置不影响,但当前错误是链接阶段的问题,和头文件搜索无关。
3. 两种场景的正确编译命令
场景一:头文件放入/usr/include、共享库放入/usr/local/lib
- 先将文件安装到系统目录:
# 复制头文件到系统头文件目录 sudo cp logWritter.h /usr/include/ # 复制共享库到系统库目录 sudo cp liblogwritter.so /usr/local/lib/ # 更新系统库缓存,让系统识别新安装的库 sudo ldconfig
- 编译C++程序:
g++ -std=c++20 full-with-logger.cpp -o loadTester -lpq -lsqlite3 -llogwritter
说明:系统默认会搜索
/usr/include(头文件)和/usr/local/lib(库文件),因此不需要额外指定-L和-I参数
场景二:直接在当前工作目录链接自定义库
第一步:修改头文件,添加C语言链接声明
修改logWritter.h,让C++编译器以C语言的规则处理函数符号:
#ifndef LOGWRITTER_H #define LOGWRITTER_H #ifdef __cplusplus extern "C" { #endif int logWritter(const char* messageData); #ifdef __cplusplus } #endif #endif // LOGWRITTER_H
说明:
__cplusplus是C编译器专属的宏,这段代码会让C程序调用该函数时,使用未修饰的C风格符号,避免名字不匹配
第二步:重新编译自定义共享库
gcc -std=gnu17 -shared -o liblogwritter.so -fPIC logWritter.c
第三步:编译C++程序
g++ -std=c++20 full-with-logger.cpp -o loadTester -L/usr/include/postgresql/libpq -L./ -lpq -lsqlite3 -llogwritter -Wl,-rpath=./ -I./
用完整路径的版本更清晰(替换为你的实际路径):
g++ -std=c++20 full-with-logger.cpp -o loadTester -L/usr/include/postgresql/libpq -L/home/username/Desktop/Current -lpq -lsqlite3 -llogwritter -Wl,-rpath=/home/username/Desktop/Current -I/home/username/Desktop/Current
内容的提问来源于stack exchange,提问作者Shahaboddin
相关产品推荐
相关产品推荐

