动态、静态库的创建和使用-程序员宅基地

技术标签: 操作系统  

1、linux库的概念

库是一种软件组件技术,库里面封装了数据和函数,提供给用户程序调用。库的使用可以使程序模块化,提高程序的编译速度,

实现代码重用,使程序易于升级。因此,对于软件开发人员,掌握这项技术是十分必要的。window系统本身提供并使用了大量的库,

包括静态链接库(.lib)和动态链接库(.dll)。类似的,linux系统也使用库。linux系统中,通常把库文件放在/usr/lib或/lib目录下。Linux库

文件由前缀lib、库名以及后缀3部分组成,其中动态库以.so作为后缀,而静态库通常以.a作为后缀。

在程序中使用静态库和动态库时,他们的载入顺序是不一样的。静态库的代码在编译时就拷贝到应用程序中,因此当多个应用程序

同时引用一个静态库函数时,内存中将会有调用函数的多个副本。这样的优点是节省编译时间。而动态库是在程序运行开始后调用

库函数时才被载入,被调函数在内存中只有一个副本,并且动态库可以在运行程序期间释放动态库所占用的内存,腾出空间供其他

程序使用。

 

2、静态库的创建和使用

创建静态库的步骤:

(1)在一个头文件中声明静态库所导出的函数

(2)在一个源文件中实现静态库所导出的函数

(3)编译源文件,生成可执行代码

(4)将可执行代码所在的目标文件加入到某个静态库中,并将静态库拷贝到系统默认的

存放库文件的目录下。

实例:

mylib.h中存放的是静态库提供给用户使用的函数的声明,mylib.c实现了mylib.h中声明的函数

头文件

#ifndef  _mylib_h_

#define  _mylib_h_

void welcome();

void outstring(const char  *str);

#endif

源文件:

 #include<stdio.h>

#include "mylib.h"

void welcome()

{

  printf("welcome to lib\n");

}

void outstring(const char  *str)

{

  if ( !str )

  {

    printf("%s\n", str);

  }

}

编译mylib.c生成目标文件

 gcc -o mylib.o -c mylib.c

将目标文件加入到静态库中,静态库为libmylib.a

ar  rcs libmylib.a  mylib.o

将静态库拷贝到linux的库目录(/usr/lib或/lib)下:(也可不拷贝,在编译时指定静态库的路径)

cp  libmylib.a     /usr/lib/libmylib.a 

以下为调用库函数的测试程序test.c

#include "lib.h"


int main()
{
  weclome();

  outstring("haha");
  return 0;
}

编译test.c生成可执行文件

gcc -o  main   test.c   -lmylib    -L .

注意: -lmylib 中 -l 为选项。 mylib为库名。 mylib是 “libmylib.a”的中间部分,linux下约定所有库

都以前缀lib开始,静态库以 .a结尾。动态库以.so结尾。在编译程序时,无需带上前缀和后缀。

linux下,可以使用ar命令来创建和修改静态库。

ar   rcs     libmylib.a   file1.o    file2.o

该命令将目标代码file1.o   和 file2.o 加入到静态库libmylib.a中,加入时如果静态库libmylib.a不存在,则会

自动创建一个静态库。rcs是命令ar的选项。

以下是ar命令 的使用格式。

ar [emulation options] [-]{dmpqrstx}[abcDfilMNoPsSTuvV]      库名  库中的成员文件名

其中的 - 不是必需的,  “dmpqrstx” 这些字母在每个命令中只能有一个且必须有一个

”abcDfilMNoPsSTuvV“中的字母在每个命令中可以有0到多个。

常用选项含义如下:

d:从库中删除成员文件

m:

p:

q:

r:

t:

x:

a:

b:

c:创建一个库

i:

l:

s:无论ar命令是否修改了库内容,都强制重新生成库符号表

u:

v:用来显示操作的附件信息

V:显示ar的版本信息

 

3、动态库的创建和使用

在linux环境下,可以很方便地创建和使用动态链接库。只要在编译函数库源程序时加上 -shared选项即可,这样所生成的可执行程序就为动态链接库。

从某种意义上讲,动态链接库也是一种可执行程序。

按一按规则,动态链接库以.so后缀。下面命令把mylib.c程序创建成了一个动态库:

gcc  -fPIC  -o  lib.o  -c  lib.c
gcc  -shared  -o  libmylib.so  lib.o

也可以直接使用一条指令:

gcc  -fPIC   -shared  -o   libmylib.so  lib.c

动态链接库创建后就可以使用了。

两种方法调用动态链接库中的函数:

(1)像使用静态库一样,通过gcc命令调用

gcc     -o   main   test.c     ./ libmylib.so

gcc -o main test.c -lmylib -L .

需要把 libmylib.so   放入到 系统指定的目录下(/etc/ld.so.conf 配置这个路径)

执行:

./main

(2)通过系统调用来使用动态链接库

#include <dlfcn.h>

void *dlopen(const char *filename, int flag);

打开指定名字的动态链接库,并返回一个句柄

char *dlerror(void);

动态链接库中的函数执行失败时,dlerror返回出错信息;若执行成功,则返回NULL

void *dlsym(void *handle, const char *symbol);

根据动态链接库的句柄与函数名,返回函数名对应的函数的地址

int dlclose(void *handle);

关闭动态链接库,handle是调用dlopen函数返回的句柄。

Link with -ldl. 

以上的函数在库中,编译调用这些库函数的程序需要 链接库   -ldl

------------------------------------------------------

dlopen函数的参数flag可取的值有:

RTLD_LAZY:需要在dlopen返回前,对于动态库中存在的未定义的变量(如外部变量extern,也可以是函数)不执行解析,也就是

不解析这个变量的地址

RTLD_NOW:需要在dlopen返回前,解析出所有未定义符号,如果解析不出来,在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......

RTLD_GLOBAL:使库中被解析出来的变量在随后的其他链接库中也可以使用,即全局有效。

实例:

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

int main()
{
    void *handle;
    char *error;
    void (*welcome)();

    if ((handle = dlopen("./libmylib.so", RTLD_LAZY)) == NULL)
    {
        printf("dlopen error:");
        exit(1);
    }

    welcome = dlsym(handle, "weclome");

    if ((error =dlerror()) != NULL)
    {
        perror("dlerror error:");
        exit(1);
    }

    welcome();
    
    dlclose(handle);


    return 0;
}

编译:

gcc -o main test.c -ldl

./main

程序成功调用了动态链接库libmylib.so中的welcome函数。通过在程序中调用系统函数来使用动态链接库时,

动态链接库要指定所在的路径。

注意:这种调用方式,不要把动态库拷贝到系统指定的动态库目录下。

 

转载于:https://www.cnblogs.com/zhangxuan/p/6760586.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30834019/article/details/97944619

智能推荐

c语言按字典升序输出方程解,C语言:输入10个姓并按字典序的升序排序-程序员宅基地

文章浏览阅读1.3k次。满意答案wh28612862013.11.21采纳率:49%等级:11已帮助:7955人#include #include struct xing//用来存放姓的结构体{char name[20];};void main(){int i,j;char str[20];struct xing ren[10];//结构体数组,用来建立多少个人来存放的for (i=0;i<10;i++){..._输入10个城市的名字,按照字典序列进行排序

LAMP 关键数据集锦技术选项参考_lamp 技术指标-程序员宅基地

文章浏览阅读2.7k次。LAMP 关键数据集锦技术选项参考源自日积月累自己的其他人的经验总结 负载均衡 LVS工作在四层,内核态,性能极高,有VIP功能,配合 keepalived 做有效的 心跳检查和负载均衡安装配置麻烦,HAProxy工作在四层到七层,功能强大,有VIP功能,配置简单,CPU占用高Nginx工作在七层,应用层功能多,配置简单,无法支持VIP功能负载均衡器测试数据软件 每秒并发量 CPU_lamp 技术指标

html ol标签用罗马数字,HTML重点标签总结-程序员宅基地

文章浏览阅读564次。本文的目的通过重点标签的学习前进一、 iframe 的学习iframe通俗的的理解就是,可以在页面里面嵌套新的页面它的使用会使页面变卡,一般会有一个固定的尺寸,默认的。他也属于可替换元素行列。我们可以通过CSS来改变尺寸frameborder消除边框name属性与a标签结合aaaaa标签的链接会在iframe的内嵌窗口里面打开二、a标签的学习a标签四种常见的targettopQQ //在新的页面打..._html什么字体支持罗马数字

js获取当前时间显示在页面上_js 当前时间-程序员宅基地

文章浏览阅读4.8k次。&lt;div id="time"&gt; &lt;/div&gt;&lt;script&gt;window.onload=function(){//定时器每秒调用一次fnDate()setInterval(function(){fnDate();},1000);}//js 获取当前时间function fnDate(){var oDiv=document.getElem..._js 当前时间

Qt加载qss文件_qt的qss文件在哪-程序员宅基地

文章浏览阅读8.8k次。试验环境:visual studio 2015,Qt5.7.1 1.在自己建立的qt项目的Resource目录下新建一个文本文件,改名为*.qss例如下面随便编写一个qss,试验运行后是否生效mainwindow.qssQDockWidget{ border: 20px solid rgb(255,0,0); background: blue;}QWidget{ b..._qt的qss文件在哪

上穷碧落下黄泉,两处茫茫皆不见——python面向对象类型方法和反射_python某市新建成了地铁,车票价格如下:1—4站2元,5—7站3元,8—9站4元,10站以上5-程序员宅基地

文章浏览阅读299次。临邛道士鸿都客,能以精诚致魂魄。为感君王辗转思,遂教方士殷勤觅。排空驭气奔如电,升天入地求之遍。上穷碧落下黄泉,两处茫茫皆不见。忽闻海上有仙山,山在虚无缥缈间。楼阁玲珑五云起,其中绰约多仙子。中有一人字太真,雪肤花貌参差是。金阙西厢叩玉扃,转教小玉报双成。闻道汉家天子使,九华帐里梦魂惊。揽衣推枕起徘徊,珠箔银屏迤逦开。云鬓半偏新睡觉,花冠不整下堂来。1 类中的方法1.1..._python某市新建成了地铁,车票价格如下:1—4站2元,5—7站3元,8—9站4元,10站以上5

随便推点

【验证成功】eZ-FET Lite 5528 官方修改版_ez-fet下载器-程序员宅基地

文章浏览阅读881次。立创链接烧写步骤(同时也是launchpad板载ezfet固件恢复步骤):STEP1:找一个可以烧写5528的烧写器,launchpad板载的Ez-FET或者FET430UIF都可以,按照标识连接到目标板上。STEP2:电脑上安装UniFlash工具,下载 Ez-FET lite的资源包STEP3:解压资源包,找到eZ-FET lite rev 1.10 Release Package\Firmware\EZFET_LITE_Rev1_1_BSL_1_1.txt这个固件文件,复制出来S_ez-fet下载器

Matlab机器学习和深度学习APP之Regression Learner_matlab regression learner-程序员宅基地

文章浏览阅读1.2w次,点赞11次,收藏100次。Matlab机器学习App之Regression Learner使用笔记目录软件与数据准备Regression Learner具体使用合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入目录软件与数据准备我之前用的是matlabR2016_matlab regression learner

Maven中设置阿里云中央仓库-程序员宅基地

文章浏览阅读1.9w次,点赞2次,收藏3次。把Maven中央仓库换成阿里云后,下载速度快了很多!配置如下:修改maven根目录下的conf文件夹中的setting.xml文件,内容如下:< !-- 在mirrors 中配置 mirror --><mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>

最小二乘法拟合矩形边缘_matlab拟合矩形-程序员宅基地

文章浏览阅读2.1k次。最小二乘法拟合直线步骤:(1)分离出目标(如下二值图像中的黑色区域);(2)提取目标边缘坐标;(3)查找所要拟合的边缘坐标;(4)最小二乘法拟合直线。在本文中使用Zernike矩检测目标的亚边缘坐标。根据MATLAB中坐标数据的特点分离出所需坐标数据,这里以水平边缘坐标的纵坐标离散程度不大为查找的条件提取出水平边缘坐标。实验图和结果图如下所示:MATLAB实现:BW=imread("xx.jpg");Coor=zernike7(BW);%查找水平边缘的坐标delta=2;%控制坐标范_matlab拟合矩形

高级数据结构实验(Kruskal算法)C语言实现_kruskal算法代码c语言实现-程序员宅基地

文章浏览阅读971次。高级数据结构实验(Kruskal算法)C语言实现实验目的:1.掌握并查集的合并优化和查询优化2.掌握Kruskal算法3.能够针对实际问题,能够正确选择贪心策略4.能够针对选择的贪心策略,证明算法的正确性5.能够正确分析算法的时间复杂度和空间复杂度实验内容:采用Kruskal算法生成最小生成树,并采用并查集的合并优化和查询优化。实验思路:使用Kruskal算法解决稀疏图解决最小生成树问题效率较高,并使用并查集这种数据结构实现了isConnected()和unionElements()两种_kruskal算法代码c语言实现

webService接口调用的通用方法_调用webservice @webparam-程序员宅基地

文章浏览阅读1.1k次。这里写自定义目录标题webService接口调用的通用方法具体方法如下如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入webService接口调用的通用方法webService接口调用的通用方法,一定要注意使用的URL中‘/’ 一定不能多,也一定不能少,否则会出现问题具体方法如下/**调用webS_调用webservice @webparam

推荐文章

热门文章

相关标签