在Linux系统中开发应用时(C++),经常会遇到需要链接第三方库的情形。有些第三方库是系统默认存在的,有些是自行编译或设备厂商提供的,无论哪一种情况,都需要链接进应用中。
1. 链接动态库的方式
(1)指定链接路径,再指定链接库
格式:-L[lib_path] -l[lib_name]
-L用于指定动态库的存储路径,-l用于指定所要链接的动态库。
这一种情形通常用于动态库不存放于系统默认搜索路径(/usr/lib或usr/local/lib)的情况下。
如存在动态库/share/libabc.so,那么通过如下方式链接libabc.so动态库。
# -L/share -labc
注意-l后直接是abc,省略了lib和后缀.so,系统会自行查找。
(2)直接链接
格式:-l[lib_name]
当动态库直接存放于系统搜索路径下时,可直接链接,无需指定路径。
如/usr/lib/libabc.so可直接通过如下路径进行链接,无需指定路径。
-labc
(3)编译时,添加搜索路径
格式:-Wl, -rpath=[lib_path]
后续可直接指定-l[lib_name]
这种方式适用于不将第三方库放在系统默认搜索路径下,但又要统一管理第三方链接库的情形。
如创建了路径/share/libs/用于管理多个第三方库,路径下包含libabc.so,libedf.so等库。此时,可以首先在编译选项上添加搜索路径,之后可以直接链接内部所有库。
g++ ... -Wl, -rpath=/share/libs/ -labc -ledf
(4)通过环境变量添加搜索路径
通过在环境变量LD_LIBRARY_PATH中添加新的搜索路径,可以实现链接时通过直接链接库的目的。
(5)注册搜索路径(/etc/ld.so.conf)
前面提到系统有默认的链接库搜索路径,这个默认的搜索路径就是在/etc/ld.so.conf文件中指定的。开发者同样可以将其他路径添加为系统默认搜索路径。
通过如下两行制定添加默认搜索路径:
echo "/usr/local/lib64" >> /etc/ld.so.conf
ldconfig
(6)利用dl库导入
使用dl库导入动态库比较特殊,这种方式会从动态库中直接查找函数符号,并进行调用。
使用dl库导入动态链接库需要注意,如果是C++开发者,需要使用C语言将符号进行封装导出。
如下先将C++代码用C语言做二次封装
#ifdef __cplusplus
extern "C"{
#endif
int StartCmdListen()
{
MQTTCmd_ListenerTask& mqtt_listen = MQTTCmd_ListenerTask::getInstance();
mqtt_listen.Start();
return 0;
}
int StopCmdListen()
{
MQTTCmd_ListenerTask& mqtt_listen = MQTTCmd_ListenerTask::getInstance();
mqtt_listen.Stop();
return 0;
}
#ifdef __cplusplus
}
#endif
然后再使用动态库进行导出
/** 导入库 */
void* sln_node = dlopen("libabc.so", RTLD_LAZY);
if (!sln_node) {
return -1;
}
dlerror(); ///< 复位错误
/** 导入Sln创建接口 */
SlnCreate_t* SlnCreator = (SlnCreate_t*) dlsym(sln_node, "StartCmdListen"); ///< 加载外部符号
if (!SlnCreator) {
return -1;
}
2. 库文件搜索路径
搜索的先后顺序是:
(1)编译目标代码时指定的动态库搜索路径;
(2)环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
(3)配置文件/etc/ld.so.conf中指定的动态库搜索路径;
(4)默认的动态库搜索路径/lib;
(5)默认的动态库搜索路径/usr/lib。