Qt在linux环境下调用动态库,pro工程文件加载库和QLibrary加载库两种方式

2023-05-16

QT调用动态库,在编译时和运行时的方式不同,编译时可在pro文件加载或使用QLibrary类加载;运行时依赖环境变量,windows下直接把动态库拷贝到可执行文件目录即可,linux需要配置固定路径或相对路径搜索动态库(ps:windows程序默认在可执行文件所在路径搜索动态库,linux则不会)。

编译时加载:pro工程文件加载动态库so

INCLUDEPATH += 库的头文件路径
LIBS += -L PATH -lLIB,PATH是so库所在路径,LIB是库的名字(-L是库路径,-l是库名字,例如库文件是libReceiptPrint.so,后面应添加-lReceiptPrint)
collect2:ld returned 1 exit status解决方案:没有正确加载库,检测库路径,32位还是64位,库是debug版还是release版,定义了槽函数没有实现,定义了构造函数和析构函数没有实现。

INCLUDEPATH += /home/chw/HSCompany/HardWareTest/source/HardWareTest/HardWareTest/sores
CONFIG(debug,debug|release){
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Debug/bin/ -lReceiptPrint
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Debug/bin/ -lInfrared
}
else{
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Release/bin -lReceiptPrint
LIBS += -L /home/chw/HSCompany/HardWareTest/source/HardWareTest/build-HardWareTest-Desktop_Qt_5_10_1_GCC_64bit-Release/bin -lInfrared
}

cannot open shared object file: No such file or directory解决方案:
运行报错原因分析,LIBS += -LPATH -l中添加的库路径是编译链接中使用,用于生成makefile,运行时的库路径是在环境变量中搜索,linux不会搜索当前路径,库路径加入到LD_LIBRARY_PATH变量中即可(使用 LD_DEBUG=libs xxx 可查看程序查找路径);
加载库后编译正常,但是运行报错,尝试添加环境变量,QT-左侧项目-Bulid-构建环境,点击添加,变量LD_LIBRARY_PATH,值$(LD_LIBRARY_PATH):库文件路径;
在这里插入图片描述
上述是在qt中添加环境变量,软件发布以后还要在linux系统中设置环境变量,否则还会报上面的错误。

编译时加载:QLibrary加载动态库so

契机:在工程文件加载so动态库方便快捷,但遇到过一种情况,当加载多个so文件,且多个so文件有同名函数时,linux系统会以先加载的为准,后加载的被忽略,导致调用混乱,解决方法很多,大多数需要重新编译库,这里介绍使用QLibrary类加载so,不用重新编译so;
QLibrary简介:
使用QLibrary可以在程序运行时加载动态链接库,一个QLibrary的实例作用于一个单一的共享库上,QLibrary库的典型用法是去解析一个库中的导出符号,并调用该符号表示的C函数,如果该库是由C++编译器编译的,那么该函数必须被包在extern "C"块中。并且在Windows平台上,还需要使用dllexport宏来修饰该函数。
代码示例:

//例如动态库接口函数为:extern "C" int OpenPort(char* pcInPort, int iInBaud);
typedef int (*Cs_OpenPort)(char* , int );//根据动态库接口函数原型,定义一个函数指针类型
Cs_OpenPort OpenPort;//用新的类型定义一个变量

QLibrary m_ReceiptPrint;//实例化一个QLibrary对象
//加载动态库
m_ReceiptPrint.setFileName("ReceiptPrint");//关联动态库名称
bool isok = m_ReceiptPrint.load();//加载动态库,成功返回true,失败返回false
OpenPort = (Cs_OpenPort)m_ReceiptPrint.resolve("OpenPort");//解析并调用动态库的函数
int ret = OpenPort((char*)"port",38400);//到这里就可以调用动态库接口

ps:QLibrary方式代码量大容易出错,不建议大量使用,多个so库有同名函数问题在封装阶段就要想办法避免。

运行时搜索库路径:固定路径

linux系统不会默认搜索应用程序所在目录的库文件,使用指定的路径搜索动态库;
固定路径有三种方式,生成临时环境变量、写入当前用户配置文件、写入系统配置文件。
1、可在终端执行:
把=号后面替换为库的路径,验证是不是环境变量路径问题,该方法在重启系统后失效;

export LD_LIBRARY_PATH=/usr/local/lib

2、把下面语句加到 ~/.bashrc中,重启后对当前用户还有效:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

3、还有一种方法对所有用户有效,修改共享库配置文件/etc/ld.so.conf,把库路径复制到该文件,执行下面命令立即生效:

sudo ldconfig

4、另一种对所有用户有效的方法:

vim /etc/profile
#文档最后添加
export PATH=环境目录:$PATH
#生效
source /etc/profile

运行时搜索库路径:相对路径

固定路径使用中有很多问题,比如部署时需要修改配置文件;当有别的程序依赖相同名称库,但库的版本不一样时,会导致程序起不来,现场遇到过teamviewer依赖的QT库和我们用QT开发时使用的库名字一样,但版本不一样,导致程序起不来。

因此建议使用相对路径,在QT开发阶段,在pro文件指定库的搜索路径,使用-rpath指定路径为库搜索路径:

QMAKE_LFLAGS += -Wl,--rpath=./lib	#指定应用程序所在路径的相对路径为库搜索路径
QMAKE_LFLAGS += -Wl,--rpath=.		#指定应用程序所在路径为库搜索路径

补充1

qt环境加载库报错: undefined reference to symbol dlclose
在QT工程的.pro文件中添加如下内容:

LIBS += -ldl		#显式加载动态库的动态函数库

补充2:QT加载静态库.a文件

只能在pro文件加载,不能通过QLibrary加载,在pro文件加载方式和动态库类似,比如静态库名是libTool_Fun.a,加载方式如下:

INCLUDEPATH += /home/chw/HSCompany/QSRM/Pdjserver/dbTest/dbTest//头文件所在路径
LIBS += -L /home/chw/HSCompany/QSRM/Pdjserver/dbTest/build-dbTest-Desktop_Qt_5_10_1_GCC_64bit-Debug/bin  -lTool_Fun//LIBS += -L 库路径 -l库名称

包含头文件后即可使用,注意静态库是直接编译进可执行文件,因此发布以后不需再依赖库。
ps1:生成静态库时命名规则是lib***.a,qt生成的静态库默认是这种命名规则,gcc 编译-o指定静态库文件名也要用这种命名规则,否则在qt中加载时可能失败。
ps2:QT在调用c语言编译的静态库时,发现pro加载库成功,但调用接口时报错,可能是C++和C兼容问题,把头文件中的静态库接口用extern "C"包裹:

extern "C" {
	//c静态库接口
}

extern "C"的作用:指示编译器这部分代码按C语言方式进行编译,而不是C++方式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt在linux环境下调用动态库,pro工程文件加载库和QLibrary加载库两种方式 的相关文章

随机推荐

  • studio one 3 机架声道设置_Lenovo UC30 声卡驱动跳线VST机架跳线

    只要是支持ASIO的声卡 xff0c 都可以使用宿主机架软件 xff0c 而机架设置好ASIO后 xff0c 还需要设置一下 xff0c 也就是设置麦克风 音乐的输入和麦克风的人声进入到经由机架挂载的效果插件 xff0c 调试后的混音的输出
  • Linux大小端转换实现

    实现 include lt byteswap h gt include lt stdint h gt 64 brief 8字节类型的字节序转化 template lt class T gt typename std enable if lt
  • Vins-Mono 论文 && Coding 一 7(2). pose_graph: 回环检测 && 重定位

    一 处理关键帧流程 void PoseGraph addKeyFrame KeyFrame cur kf bool flag detect loop 1 shift to base frame 将当前帧 pose 转换到 drift fre
  • 浅谈STM32串口通信(一)基本介绍和一个字节传输的实现

    文章目录 0 传输引脚1 传输一个字节1 1 发送一个字节1 2 接收一个字节 2 代码2 1 配置2 2 发送一个字节2 3 接收一个字节 0 传输引脚 串口收发共需要三根线 其中 TX脚为发送引脚 RX脚为发送引脚 GND为地 作为电平
  • 图像融合(Image Fusion)简介

    图像融合 Image Fusion 是用特定的算法将两幅或多幅图像综合成一幅新的图像 融合结果由于能利用两幅 或多幅 图像在时空上的相关性及信息上的互补性 xff0c 并使得融合后得到的图像对场景有更全面 清晰的描述 xff0c 从而更有利
  • IP地址分类

    大家好呀 xff0c 我是请假君 xff0c 今天又来和大家一起学习数通了 xff0c 今天要分享的知识是IP地址的分类 各个网段内具有的IP节点数各不相同 xff0c 为了适应这种需求 xff0c IP地址被分成五类 1 A类IP地址的第
  • 解决映射网络驱动器自动断开问题

    解决映射网络驱动器自动断开问题 hzq0201 2012 04 13 06 47 36 2777 收藏 2 版权 映射的网络驱动器在一段时间自动断开 xff0c 是由于服务器服务自动断开连接功能的默认超时期限造成的 xff0c 我们可以通过
  • vector深度探索

    声明 xff1a 本文中所有图件都来自B站侯捷老师授课视频 vecctor 底层实现原理 图1 GNU2 9 实现的容器vector vector 的内存是动态增长的 xff0c vector 最重要的三个成员变量为 三个迭代器 xff1a
  • 发送一个http请求以及url三部分组成和语法

    浏览器从URL中解析出服务器的主机名浏览器讲服务器的主机名转化成服务器的IP地址 xff08 DNS解析 xff09 浏览器将端口号从URL解析出来浏览器建立一条鱼web服务器的TCP连接浏览器向服务器发送一条http请求报文服务器向浏览器
  • 结构体对齐规则

    结构体 xff1a 结构体 xff08 struct xff09 是由一系列具有相同类型或不同类型的数据构成的集合 因为这一特性 xff0c 方便了开发者在使用的过程中可以将需要的不同的数据类型放在一起 xff0c 做成我们需要的数据类型
  • GPS坐标用于机器人定位的简单处理

    文章目录 前言一 GPS数据格式二 GPS坐标转换二维坐标原理三 参考代码1 转换经纬度格式2 解析通过串口获得的NMEA数据3 将经纬度转换为xy平面二维坐标 前言 最近工作上面接触使用GPS的NMEA数据为机器人提供平面坐标定位 xff
  • 学完C++基础后再学什么?

    学完 xff1f 那是什么程度 xff1f STL用得熟练吗 xff1f 算法和数据结构掌握得怎么样呢 xff1f 会写界面吗 xff1f BOOST呢 xff1f 像楼上所说的换一种语言 xff0c 简直是痴人说梦 xff0c 如果不深入
  • 视觉SLAM十四讲:回环检测-知识点+代码

    目录 基于外观的几何关系1 基础知识1 1 准确率和召回率1 2 词袋模型1 3 字典1 4 字典的数据结构1 5 相似度的计算1 6 相似度评分的处理1 7 检测回环后的验证 2 实践与代码解析2 1 创建字典2 2 相似度计算 回环检测
  • QT笔记--QT内类的层次关系,以及控件从属关系

    QT窗口界面使用的类层次如下 只包含了直接使用部分 界面上每一个创建的控件 xff0c 都是一个控件类的对象 xff0c 定义在头文件ui mainwindoow h的类UI MainWindow中 xff0c 并且其中的成员函数setup
  • C_带参数的宏定义

    C 带参数的宏定义 xff23 语言允许宏带有参数 在宏定义中的参数称为形式参数 xff0c 在宏调用中的参数称为实际参数 对带参数的宏 xff0c 在调用中 xff0c 不仅要宏展开 xff0c 而且要用实参去代换形参 带参宏定义的一般形
  • 十进制数转换成十六进制数~C语言

    include lt stdio h gt 下面将整数a转换成十六进制输出的字符串 原理 xff1a 1 xff0c 首先知道0b100000 61 0b10000 2 61 0b1000 2 61 0b100 2 61 0b10 2 利用
  • Qt实现线程安全的单例模式

    实现方式 1 实现单例 把类的构造函数 拷贝构造函数 赋值操作符定义为private的 xff1b 把获取单例的接口和唯一的实例指针定义为static的 xff0c 不需要实例化 xff0c 直接通过类名即可访问 2 支持多线程 采用双重校
  • 文本文件和二进制文件的差异和区别

    广义上的二进制文件包括文本文件 xff0c 这里讨论的是狭义上的二进制文件与文本文件的比较 xff1a 能存储的数据类型不同 文本文件只能存储char型字符变量 二进制文件可以存储char int short long float 各种变量
  • Qt实现记录日志文件log

    概述 Qt有两种实现记录日志的方式 xff0c 第一种是安装自定义的Qt消息处理程序 xff0c 自动输出程序产生的调试消息 警告 关键和致命错误消息的函数 xff1b 第二种是自定义一个类 xff0c 可以在程序指定位置打印输出指定的内容
  • Qt在linux环境下调用动态库,pro工程文件加载库和QLibrary加载库两种方式

    QT调用动态库 xff0c 在编译时和运行时的方式不同 xff0c 编译时可在pro文件加载或使用QLibrary类加载 xff1b 运行时依赖环境变量 xff0c windows下直接把动态库拷贝到可执行文件目录即可 xff0c linu