嵌入式Linux应用开发基础-现有动态库so的使用

前言

最近做嵌入式Linux项目,需要调用客户提供的现成的动态库(so文件,包含对应头文件),我这边用的是cmake来构建。
此篇文章主要是记录一下嵌入式Linux的动态库的使用,与君共勉!

一、通过cmake使用so库和对应的头文件
1.包含so库对应的头文件目录:
(1)当你调用了so库对应的头文件,为了编译通过,需要把so库对应的头文件的目录包含进去
(2)cmake通过include_directories指令包含目录,这个指令必须在生成可执行文件add_executable指令之前
(3)${PROJECT_SOURCE_DIR}是相对地址前缀,代表此CMakeLists.txt所在的目录
(4)目录2和目录4为需要包含的头文件的目录

#包含目录的例子
include_directories(${PROJECT_SOURCE_DIR}/目录1/目录2${PROJECT_SOURCE_DIR}/目录3/目录4
)

2.链接so库文件:
(1)动态库只有在调用它的进程启动的时候才会被加载,因此在编译的时候,这个so库甚至不需要在工程里,只要对应的头文件目录包含了,就能编译通过,生成可执行文件
(2)生成可执行文件后,要把可执行文件用到的动态库进行链接,可执行文件运行的时候才知道要加载哪些动态库(能不能找到库另说)
(3)camke通过target_link_libraries指令链接库,这个指令必须在生成可执行文件add_executable指令之后
(link_libraries指令也是链接库,但是必须在生成可执行文件add_executable指令之前。因为静态库需要编译时加载,因此静态库一般都用这个指令,这也是使用静态库的可执行文件比使用动态库的可执行文件更大的原因)
(4)AAA是生成的可执行文件名;BBB是动态库名字的简写:动态库的名字必须是libXXX.so,填名字时省略"lib"和".so",只填XXX就行

#可执行文件名:AAA,动态库名字:libBBB.so
#链接动态库
target_link_libraries(AAA BBB)

二、通过cmake安装so库到target目录
通过以上步骤,可执行文件已经编译完成,并且可执行文件运行的时候需要加载哪些动态库了。接下来我们要让可执行文件能正确地搜索到需要的库!

1.安装so库到target目录:
(1)可执行文件运行的时候,是在target目录里搜索库的
(2)嵌入式Linux 系统把 target目录里的/lib 和 /usr/lib 两个目录作为默认的库搜索路径
(3)camke通过install指令进行安装。它可以用来安装很多内容,可以包括目标二进制、动态库、静态库以及文件、目录、脚本等。其中,so库可以通过目标二进制(TARGETS)和普通文件(FILES)来进行安装

install(TARGETS <target>... [...])
install({FILES | PROGRAMS} <file>... [...])
install(DIRECTORY <dir>... [...])
install(SCRIPT <file> [...])
install(CODE <code> [...])
install(EXPORT <export-name> [...])

(4)如果是别人提供的so库,按照普通文件(FILES)来安装,其中${PROJECT_SOURCE_DIR}是相对地址前缀,代表此CMakeLists.txt所在的目录;DESTINATION是target文件夹

#动态库名字:libAAA.so
#目标安装位置:target/usr/lib
#在target安装动态库
install(FILES ${PROJECT_SOURCE_DIR}/目录1/.../目录N/libAAA.so DESTINATION /usr/lib)

(5)如果是自己生产的so库,按照目标二进制(TARGETS)来安装,先通过add_library生成动态库,再把动态库名字作为TARGETS名进行安装

#源文件名字:AAA.c,生成的动态库名字:libAAA.so
#生成动态库
add_library(AAA SHARED ${PROJECT_SOURCE_DIR}/AAA.c)#目标安装位置:target/usr/lib
#在target安装动态库
INSTALL(TARGETS AAALIBRARY DESTINATION /usr/lib
)

三、代码里调用so库(显示调用/隐式调用)
1.隐式调用
(1)隐式调用由系统完成,对程序员是不可感知的
(2)写代码时使用方法和静态库一样,包含头文件,直接使用数据结构和接口函数即可

2.显式调用
(1)显式调用的so库,如果只需要用到接口函数,不需要数据结构的话,连头文件的都不需要包含就能用
(2)显式调用则要求程序员在调用时,指明要加载的动态库的名称和要调用的函数名称
(3)显式调用是在调用so库时才申请空间,使用结束可释放,会相对更省空间
(4)函数介绍:

dlopen
函数原型:void *dlopen(const char *libname,int flag);
功能描述:dlopen必须在dlerror,dlsym和dlclose之前调用,表示要将库装载到内存,准备使用。如果要装载的库依赖于其它库,必须首先装载依赖库。如果dlopen操作失败,返回NULL值;如果库已经被装载过,则dlopen会返回同样的句柄。

参数中的libname一般是库的全路径,这样dlopen会直接装载该文件;如果只是指定了库名称,在dlopen会按照下面的机制去搜寻:

a.根据环境变量LD_LIBRARY_PATH查找

b.根据/etc/ld.so.cache查找

c.查找依次在/lib和/usr/lib目录查找。

flag参数表示处理未定义函数的方式,可以使用RTLD_LAZY或RTLD_NOW。RTLD_LAZY表示暂时不去处理未定义函数,先把库装载到内存,等用到没定义的函数再说;RTLD_NOW表示马上检查是否存在未定义的函数,若存在,则dlopen以失败告终。

dlerror
函数原型:char *dlerror(void);
功能描述:dlerror可以获得最近一次dlopen,dlsym或dlclose操作的错误信息,返回NULL表示无错误。dlerror在返回错误信息的同时,也会清除错误信息。

dlsym
函数原型:void *dlsym(void *handle,const char *symbol);
功能描述:在dlopen之后,库被装载到内存。dlsym可以获得指定函数(symbol)在内存中的位置(指针)。如果找不到指定函数,则dlsym会返回NULL值。但判断函数是否存在最好的方法是使用dlerror函数,

dlclose
函数原型:int dlclose(void *);
功能描述:将已经装载的库句柄减一,如果句柄减至零,则该库会被卸载。如果存在析构函数,则在dlclose之后,析构函数会被调用。

//显式调用例程
typedef struct
{void *pd;int (*Init_func)(void* param);int (*getData_func)(unsigned char* buff, int bufflen);	
}func_t;func_t fun;
//打开动态链接库,其中./usr/lib/libAAA.so"为库在target的位置
fun.pd=dlopen("./usr/lib/libAAA.so",RTLD_LAZY);
if (fun.pd==NULL) /* 若打开失败则退出 */ 
{perror(dlerror()); perror(stderr);return -2;
}//动态链接接口函数,其中AAA_Init为库里的接口函数
fun.Init_func=dlsym(fun.pd,"AAA_Init");
error=dlerror();
if (error) /* 若出错则退出 */ 
{ //perror(error,stderr); perror(error);perror(stderr);return -3; 
}//动态链接接口函数,其中AAA_Get_ModuleData为库里的接口函数
fun.getData_func=dlsym(fun.pd,"AAA_Get_ModuleData");  /* 动态链接接口函数 */ 
error=dlerror();
if (error) /* 若出错则退出 */ 
{ //perror(error,stderr); perror(error);perror(stderr);return -3; 
}//调用链接的接口
uint8_t buf[2]={0};
if (fun.Init_func(buf) < 0)
{perror("Init_funcfailed!\n");return -4;
}//调用链接的接口
uint8_t dataBuf[256]={0};
if(fun.getData_func(dataBuf,sizeof(dataBuf))>0)
{...
}//关闭链接,释放内存
dlclose(fun.pd);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/46732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01数据结构 - 顺序表

这里是只讲干货不讲废话的炽念&#xff0c;这个系列的文章是为了我自己以后复习数据结构而写&#xff0c;所以可能会用一种我自己能够听懂的方式来描述&#xff0c;不会像书本上那么枯燥和无聊&#xff0c;且全系列的代码均是可运行的代码&#xff0c;关键地方会给出注释^_^ 全…

C++客户端Qt开发——常用控件(容器类控件)

6.容器类控件 ①GroupBox 带标题分组框 属性 说明 title 分组框的标题 alignment 分组框内部内容的对齐方式 flat 是否是"扁平"模式 checkable 是否可选择 设为true,则在title前方会多出一个可勾选的部分. check 描述分组框的选择状态&#xff08;前提…

数据结构(5.1)——树的性质

结点数总度数1 结点的度——结点有几个孩子(分支) 度为m的树、m叉树的区别 度为m的树第i层至多有 个结点(i>1) 高度为h的m叉树至多有 个结点 高度为h的m叉树至少有h个结点 、高度为h&#xff0c;度为m叉树至多有hm-1个结点 具有n个结点的m叉树的最小高度为 总结

通过角点进行水果的果梗检测一种新方法

一、前言 在前面的《数字图像处理与机器视觉》案例一&#xff08;库尔勒香梨果梗提取和测量&#xff09;中主要使用数学形态学的方法进行果梗提取&#xff0c;下面给出一种提取果梗的新思路。 众所周知&#xff0c;一般果梗和果实在边缘处角度有较大突变&#xff0c;可以通过合…

探索WebKit的CSS列表与标记:美化列表的艺术

探索WebKit的CSS列表与标记&#xff1a;美化列表的艺术 CSS列表和标记是网页设计中用于增强列表展示效果的重要工具。WebKit&#xff0c;作为多种现代浏览器的内核&#xff0c;包括Safari、QQ浏览器等&#xff0c;提供了对CSS列表和标记的广泛支持。本文将深入探讨WebKit对CSS…

spring security源码追踪理解(一)

一、前言 近期看了spring security相关的介绍&#xff0c;再加上项目所用若依框架的底层安全模块也是spring security&#xff0c;所以想从源码的角度加深下对该安全模块的理解&#xff08;看源码之前&#xff0c;我们要先有个意识&#xff0c;那就是spring security安全模块主…

Solus Linux简介

以下是学习笔记&#xff0c;具体详实的内容请参考官网&#xff1a;Home | Solus Solus Linux 是一个独立的 Linux 发行版&#xff0c;它以其现代的设计、优化的性能和友好的用户体验而著称。以下是一些关于 Solus Linux 的最新动向和特点&#xff1a; 1. **最新版本发布**&a…

第122天:内网安全-域信息收集应用网络凭据CS 插件AdfindBloodHound

目录 前置知识 背景和思路 判断是否在域内 案例一&#xff1a;架构信息类收集-网络&用户&域控等 案例二&#xff1a;自动化工具探针-插件&Adfind&BloodHound Adfind(域信息收集工具) ​BloodHound&#xff08;自动化域渗透工具&#xff09; 前置知识 本…

计算机视觉10 总结

全卷积网络&#xff08;FCN&#xff09;是计算机视觉中用于处理图像任务的重要网络架构。 核心要点&#xff1a; 与传统 CNN 不同&#xff0c;FCN 将最后的全连接层替换为卷积层&#xff0c;从而能够处理任意尺寸的输入图像&#xff0c;并保留了空间信息。优点包括可处理不同大…

java基础万字笔记

前言 此篇文章为本人在初学java时所记录的java基础的笔记&#xff0c;其中全面记录了java的基础知识点以及自己的一些理解和要注意的点。由于该笔记是边学边记录而成&#xff0c;所以基本很多模块内都会有一些我本人后期记录的知识穿插进去&#xff0c;导致一些模块内的内容并…

搭建个人智能家居 7 - 空气颗粒物检测

搭建个人智能家居 7 - 空气颗粒物检测 前言说明PMS5003ESPHomeHomeAssistant结束 前言 到目前为止&#xff0c;我们这个智能家居系统添加了4个外设&#xff0c;分别是&#xff1a;LED灯、RGB灯、DHT11温度传感器和SGP30。今天继续添加环境测量类传感器“PMS5003空气颗粒物检测…

Django获取request请求中的参数

支持 post put json_str request.body # 属性获取最原始的请求体数据 json_dict json.loads(json_str)# 将原始数据转成字典格式 json_dict.get("key", "默认值") # 获取数据参考 https://blog.csdn.net/user_san/article/details/109654028

Windows FFmpeg 开发环境搭建

FFmpeg 开发环境搭建 FFmpeg命令行环境搭建使用FFmpeg官方编译的库Windows编译FFmpeg1. 下载[msys2](https://www.msys2.org/#installation)2. 安装完成之后,将安装⽬录下的msys2_shell.cmd中注释掉的 rem set3. 修改pacman 镜像源并安装依赖4. 下载并编译源码 FFmpeg命令行环境…

39、PHP 实现二叉树的下一个结点(含源码)

题目&#xff1a; PHP 实现二叉树的下一个结点 描述&#xff1a; 给定一个二叉树和其中的一个结点&#xff0c;请找出中序遍历顺序的下一个结点并且返回。 注意&#xff0c;树中的结点不仅包含左右子结点&#xff0c;同时包含指向父结点的指针。 <?php /*class TreeLinkN…

vite+vue3项目初始化搭建

vitevue3项目初始化搭建 "nodejs": v18.19.0 "pnpm": 8.15.0 "vue": v3.4.21 "vite": v5.2.01.创建项目 Vite中文官网 pnpm create vitelatest项目名字&#xff1a;gd_web 选择框架&#xff1a;Vue3 选择语言&#xff1a;JavaScrip…

基于springboot和mybatis的RealWorld后端项目实战三之添加swagger

pom.xml添加依赖 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><arti…

解决网页中的 video 标签在移动端浏览器(如百度访问网页)视频脱离文档流播放问题

问题现象 部分浏览器视频脱离文档流&#xff0c;滚动时&#xff0c;视频是悬浮出来&#xff0c;在顶部播放 解决方案 添加下列属性&#xff0c;可解决大部分浏览器的脱离文档流的问题 <videowebkit-playsinline""playsInlinex5-playsinlinet7-video-player-t…

JS【详解】真值 vs 假值(虚值 / falsy 值)

假值&#xff08;虚值 / falsy 值&#xff09; 转换为布尔类型后&#xff0c;结果为 false 的数据即假值&#xff0c;共 7 种 falsenullundefined0-0NaN空字符串 —— "" 或 或 【实战】删除数组中的假值 let list [null, 1, undefined, 2, NaN, 3]; let resul…

AI辅助自动驾驶技术在2024年的发展与趋势

文章目录 综述 2024 年 AI 辅助研发趋势 第一章&#xff1a;引言 1.1 背景介绍 1.2 AI在自动驾驶中的地位和作用 1.3 2024年自动驾驶技术的现状 1.4 论文结构 第二章&#xff1a;AI技术在自动驾驶中的应用 2.1 深度学习算法在自动驾驶中的应用 2.2 数据分析与模式识别…

谷类大米农业行业网站源码系统 带完整的安装代码包以及搭建部署教程

系统概述 在当今数字化时代&#xff0c;农业行业也逐渐迈向信息化、智能化。为了满足谷类大米农业行业的信息化需求&#xff0c;我们推出了一款专为该行业设计的网站源码系统。该系统不仅具备丰富的行业特色功能&#xff0c;而且提供了完整的安装代码包以及详细的搭建部署教程…