动态库的使用方法

在编写程序时,动态库是常常用到的工具,在vs等编程环境下只需要,完成工程的本地化配置或是直接将dll配置到环境变量即可(不推荐,毕竟小题大做了),而对于像楼主这样刚刚接触Linux操作系统的菜鸟来说,配置动态(共享)库还不是一个简单的问题。

在介绍动态库的调用方法之前,先介绍一下动态库的编译(如何生成so文件)

需要一个包含几个方法声明的头文件和对应的定义文件。例如

//so_test.h 头文件
#include "stdio.h"
void test_a();
void test_b();
void test_c();
//test_a.c:
#include "so_test.h"
void test_a()
{
  printf("this is in test_a...\n");
}
//test_b.c:
#include "so_test.h"
void test_b()
{
  printf("this is in test_b...\n");
}
#include "so_test.h"
void test_c()
{
  printf("this is in test_c...\n");
}

将上述so_test.h test_a.c test_b.c test_c.c 文件放与同一目录下,执行

gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

此时,我们可以看到 多出了一个libtest.so文件,这里的命名有些讲究,应该命名为lib+xxxx+.so后面再解释为什么,这就是我们刚刚生成的共享库文件。

-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的(好像不是必须的哦)

-shared : 该选项指定生成动态连接库,这个是必须的

到这来似乎完成了共享库的编写,那么我们先来简单的介绍下两种调用方式:

①隐式调用

②显示调用

简单来时,隐式调用就是指在我们的程序代码中,没有定义我们调用了哪个共享库,只是包含了某个贡献库的头文件而已,而在编译的时候需要指明共享库。我们继续用示例说明:

#include "so_test.h"
int main()
{
test_a();
test_b();
test_c();
return 0;
}

很简单的调用,和普通的链接没什么区别啊!是的不过在编译的时候要花费一些功夫

 gcc test.c -L. -ltest -o test

-L. : 表示需要链接的共享库在当前目录;

-Itest : 表示调用的共享库的文件名为 lib+test+.so 即libtest.so

我们运行一下生成的test文件

无法打开shared object file

为什么不行,别急 我们借助ldd命令查看下 test文件的链接情况

ldd text

我们刚刚写的libtest.so 就和你放在一个文件夹居然说找不到,服了(:зゝ∠)

话说链接库可以从以下五个位置检索

①环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录;

②文件/etc/ld.so.cache中找到的库的列表,由ldconfig命令刷新;

③目录usr/lib;

④目录/lib;

⑤当前目录;

我建议还是将我们生成的共享库拷贝到/usr/lib/或/lib目录下,修改LD_LIBRARY_PATH不是和windows环境下改环境变量一样小题大做吗?(个人看法请大神指正)

cp libtest.so /usr/lib/

现在我们发现他能找到我们写的共享库了,也就能正常运行了。

好的接下来看看显示调用

此时我们已经写好了libtest.so共享库,并且已拷贝至/usr/lib/目录下

显示调用,就是在代码中明确指明我们需要调用的共享库,而不需要在编译时指明,因此我们需要一些特殊的函数完成上述功能。

我们需要用到一个头文件dlfcn.h 和其对应的四个函数。下面在介绍具体步骤再加以说明。

①把dlfcn.h系统头文件包含进来

②用dlopen()函数打开库文件,并指定打开方式;

dllope()有两个参数

第一个参数为共享库的名称,能取到的位置不在累述了。

第二个参数为打开共享库的方式。有两个取值

①RTLD_NOW:将共享库中的所有函数加载到内存

②RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时方加载某函数

返回值是一个void *指针

③用dlerror()函数测试是否打开成功,并进行错误处理,返回值是一个char *;

④用dlsym获得函数地址,存放在一个函数指针中,调用格式是dlsym(void *,”fcnname”);

⑤用获得的函数指针进行函数调用。

⑥程序结束时用dlclose(void *)关闭打开的动态库,防止资源泄露。

#include <dlfcn.h>         //包含头文件
#include "so_test.h"       //包含共享库头文件
int main(int argc,char *argv[])
{
   void(*pT)();            //申请一个与共享库对应的函数指针
   void *Handle=dlopen("libtest.so",RTLD_LAZY);
                           //打开共享库,并有void指针 Handle保存
   if(Handle==NULL)        //检测是否打开成功
   {
       printf("Fail load library\n");
       return -1;
   }
   char * pE=dlerror();    //检测函数是否打开成功
   if(pE!=NULL)
   {
       printf("%s\n",pE);
       return -1;
   }
   pT=dlsym(Handle,"test_a");    //调用具体的函数
   pE=dlerror();                 //再次检测函数打开是否成功
   if(pE!=NULL)
   {
       printf("%s\n",pE);
       return -1;
   }
   (*pT)();                      //调用共享库的函数
   dlclose(Handle);              //关闭共享库

   return 0;
}

编译命令为

gcc -o main -ldl test.c

-ldl : 指明生成对象需要使用共享库,但不用具体指明哪个共享库

(^o^)/~ 调用动态(共享库)的方法就先说到这来喽!!

时间: 2024-09-29 02:26:53

动态库的使用方法的相关文章

iOS中创建动态库及调用方法

去年因需要用到动态库,自己就找了好多一些 资料,最终找到了一套方法,怎么创建与使用动态库,记录一下: Xcode提供了在iOS工程中创建静态库的功能,和在MAC上创建动态库和静态库的功能. 但是没有提供在iOS工程中创建动态库的功能(苹果官方不允许程序中存在动态库链接,这样的程序会被AppStore拒),如下图:  由于苹果不支持自己创建iOS动态库,所以要想创建动态库首先要修改Xcode的配置文件使其支持具备创建iOS 动态库的功能, 经过调研和查询网上的一些资料,并经过自己测试成功,以下是修

Windows系统下静态库和动态库的使用方法

使用静态库时,我们需要别人提供的头文件和lib文件,然后在自己的工程的源文件(.cpp文件)中添加头文件和#pragma comment(lib, "静态库的路径") 使用动态库时,我们需要别人提供的头文件,引入库和动态库,然后在自己的工程的源文件(.cpp文件)中添加头文件和#pragma comment(lib, "引入库路径") 原文地址:https://www.cnblogs.com/chen-cai/p/9028449.html

动态调用动态库方法 .so

关于动态调用动态库方法说明 一.       动态库概述 1.  动态库的概念 日常编程中,常有一些函数不需要进行编译或者可以在多个文件中使用(如数据库输入/输 出操作或屏幕控制等标准任务函数).可以事先对这些函数进行编译,然后将它们放置在一些特殊的目标代码文件中,这些目标代码文件就称为库.库文件中的函数 可以通过连接程序与应用程序进行链接,这样就不必在每次开发程序时都对这些通用的函数进行编译了. 动态库是一种在已经编译完毕的程序开始启动运行时,才被加载来调用其中函数的库.其加载方式与静态库截然

Linux动态库相关知识整理

动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序, 动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执 行程序等诸多好处.作者是一个Linux后台开发,这些知识经常用到,所以 整理了一下这方面的知识.静态库相对简单,本文只关心Linux平台下的动态库. 创建动态库 这里我把一个短小却很有用的哈希函数编译成动态库做为示例,ELFhash用于对字符串做哈希,返回一个无符号整数. //elfhash.h #include <stdio.h> unsign

动态库(非MFC动态库)

一.C语言动态库 1.创建C语言动态库,并封装函数: 1)创建新工程:Win32 Dynamic-Link Library 2)添加SourceFiles文件:Cdll.c Cdll.c中的内容: //创建C的动态库 //_declspec(dllexport)声明导出 _declspec(dllexport)int Cdll_add(int add1,int add2){     return add1+add2; } _declspec(dllexport)int Cdll_sub(int 

Android WebView加载Chromium动态库的过程分析

Chromium动态库的体积比较大,有27M左右,其中程序段和数据段分别占据25.65M和1.35M.如果按照通常方式加载Chromium动态库,那么当有N个正在运行的App使用WebView时,系统需要为Chromium动态库分配的内存为(25.65 + N x 1.35)M.这是非常可观的.为此,Android使用了特殊的方式加载Chromium动态库.本文接下来就详细分析这种特殊的加载方式. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 为什么当有

Linux生成动态库系统

Linux生成动态库系统 一个.说明 Linux下动态库文件的扩展名为 ".so"(Shared Object). 依照约定,全部动态库文件名称的形式是libname.so(可能在名字中增加版本). 这样.线程函数库被称作libthread.so. 静态库的文件名称形式是libname.a.共享archive的文件名称形式是libname.sa.共享archive仅仅是一种过渡形式,帮助人们从静态库转变到动态库. 小编综合自己学习体会以及网络上较好的内容.以简单的样例介绍动态库文件的生

Linux 动态库相关知识整理

动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序,动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执行程序等诸多好处.作者是一个Linux后台开发,这些知识经常用到,所以整理了一下这方面的知识.静态库相对简单,本文只关心Linux平台下的动态库. 创建动态库 这里我把一个短小却很有用的哈希函数编译成动态库做为示例,ELFhash用于对字符串做哈希,返回一个无符号整数. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //elf

Linux系统下动态库的生成

Linux系统下动态库的生成 一.简述 Linux下动态库文件的扩展名为 ".so"(Shared Object).按照约定,所有动态库文件名的形式是libname.so(可能在名字中加入版本号).这样,线程函数库被称作libthread.so.静态库的文件名形式是libname.a.共享archive的文件名形式是libname.sa.共享archive只是一种过渡形式,帮助人们从静态库转变到动态库.      小编综合自己学习体会以及网络上较好的内容,以简单的例子介绍动态库文件的生