在dlopen()函数以指定模式打开指定的动态链接库文件。并返回一个句柄给 dlsym()的调用进程。

使用 dlclose()来卸载打开的库。

功能:打开一个动态链接库,并返回动态链接库的句柄
包括头文件:
#include <dlfcn.h>
函数定义:
void * dlopen( const char * pathname, int mode);
函数描写叙述:
mode是打开方式,其值有多个,不同操作系统上实现的功能有所不同,在linux下,按功能可分为三类:
1、解析方式
RTLD_LAZY:在dlopen返回前,对于动态库中的没有定义的符号不运行解析(仅仅对函数引用有效。对于变量引用总是马上解析)。 RTLD_NOW: 须要在dlopen返回前。解析出全部没有定义符号,假设解析不出来。在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......
2、作用范围,可与解析方式通过“|”组合使用。 RTLD_GLOBAL:动态库中定义的符号可被其后打开的其他库解析。
RTLD_LOCAL: 与RTLD_GLOBAL作用相反,动态库中定义的符号不能被其后打开的其他库重定位。 假设没有指明是RTLD_GLOBAL还是RTLD_LOCAL。则缺省为RTLD_LOCAL。
3、作用方式
RTLD_NODELETE: 在dlclose()期间不卸载库,而且在以后使用dlopen()又一次载入库时不初始化库中的静态变量。这个flag不是POSIX-2001标准。
RTLD_NOLOAD: 不载入库。 可用于測试库是否已载入(dlopen()返回NULL说明未载入,否则说明已载入),也可用于改变已载入库的flag,如:先前载入库的flag为RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)后flag将变成RTLD_GLOBAL。这个flag不是POSIX-2001标准。
RTLD_DEEPBIND:在搜索全局符号前先搜索库内的符号。避免同名符号的冲突。这个flag不是POSIX-2001标准。
返回值:
打开错误返回NULL
成功,返回库引用
编译时候要增加 -ldl (指定dl库)
比如
gcc test.c -o test -ldl
#include <stdlib.h>
#include <dlfcn.h>
#include <stdio.h> //申明结构体
typedef struct __test {
int i;
void (* echo_fun)(struct __test *p);
}Test; //供动态库使用的注冊函数
void __register(Test *p) {
p->i = 1;
p->echo_fun(p);
} int main(void) { void *handle = NULL;
char *myso = "./mylib.so"; if((handle = dlopen(myso, RTLD_NOW)) == NULL) {
printf("dlopen - %sn", dlerror());
exit(-1);
} return 0;
}
#include <stdio.h>
#include <stdlib.h> //申明结构体类型
typedef struct __test {
int i;
void (*echo_fun)(struct __test *p);
}Test; //申明注冊函数原型
void __register(Test *p); static void __printf(Test *p) {
printf("i = %dn", p->i);
} //动态库申请一个全局变量空间
//这样的 ".成员"的赋值方式为c99标准
static Test config = {
.i = 0,
.echo_fun = __printf,
}; //载入动态库的自己主动初始化函数
void _init(void) {
printf("initn");
//调用主程序的注冊函数
__register(&config);
}

主程序编译: gcc test.c -ldl -rdynamic

动态库编译: gcc -shared -fPIC -nostartfiles -o mylib.so mylib.c

主程序通过dlopen()载入一个.so的动态库文件, 然后动态库会自己主动执行 _init() 初始化函数, 初始化函数打印一个提示信息, 然后调用主程序的注冊函数给结构体又一次赋值, 然后调用结构体的函数指针, 打印该结构体的值. 这样就充分的达到了主程序和动态库的函数相互调用和指针的相互传递.

gcc參数 -rdynamic 用来通知链接器将全部符号加入到动态符号表中(目的是可以通过使用 dlopen
来实现向后跟踪).

gcc參数 -fPIC 作用: 当使用.so等类的库时,当遇到多个可运行文件共用这一个库时, 在内存中,这个库就不会被复制多份,让每一个可运行文件一对一的使用,而是让多个可运行文件指向一个库文件,达到共用. 宗旨:节省了内存空间,提高了空间利用率.

<pre name="code" class="cpp">dlsym函数:
函数原型是
void* dlsym(void* handle,const char* symbol)
该函数在<dlfcn.h>文件里。 handle是由dlopen打开动态链接库后返回的指针。symbol就是要求获取的函数的名称,函数 返回值是void*,指向函数的地址,供调用使用。

导入库函数使用方法:
 

#include <dlfcn.h>

void* handle = dlopen("./hello.so", RTLD_LAZY);

typedef void (*hello_t)();

hello_t hello = (hello_t) dlsym(handle, "hello");



hello();

dlclose(handle);

注意库函数在库中的定义要用extern“c”来申明,这样在主函数中才干通过“hello”来查找函数。申明的方式有下面两种:

extern "C" int foo;

extern "C" void bar();

            

and 



extern "C" {

     extern int foo;

     extern void bar();

}

导入类库方法:

#include "polygon.hpp" //类定义处



#include <dlfcn.h>



void* triangle = dlopen("./triangle.so", RTLD_LAZY);

create_t* create_triangle = (create_t*) dlsym(triangle, "create");



destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, "destroy");

polygon* poly = create_triangle();

// use the class



    poly->set_side_length(7);

    cout << "The area is: " << poly->area() << '\n';

// destroy the class



    destroy_triangle(poly);



    // unload the triangle library



    dlclose(triangle);



dlopen 方式调用 Linux 的动态链接库的更多相关文章

  1. .netcore在linux下使用P/invoke方式调用linux动态库

    http://www.mamicode.com/info-detail-2358309.html   .netcore下已经实现了通过p/invoke方式调用linux的动态链接库(*.so)文件 1 ...

  2. linux中动态链接库的创建与使用

    LINUX系统中动态链接库的创建与使用 http://www.cnblogs.com/ardar/articles/357321.html 正常C源文件编写,编译时-shared即可得到SO, gcc ...

  3. Linux 关于动态链接库以及静态链接库的一些概念

    库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀.例如:libhello.so libhello.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhe ...

  4. linux下动态链接库解决方案(二)

    以前写过一个关于linux下用c++写动态链接库无法通过的解决方案,今天看到<linux C程序设计-王者归来>这本书,书中有个更容易的解决方案,特此记录下来 书中使用的是c语言,我改用c ...

  5. Python调用C/C++动态链接库

    Python调用C/C++动态链接库 2013年07月26日 ⁄ 综合 ⁄ 共 3219字 ⁄ 字号 小 中 大 ⁄ 评论关闭   吐槽(可略过):不知不觉,4月份毕业,5月份进入团队,已有7个月.大 ...

  6. 【转】Python调用C语言动态链接库

    转自:https://www.cnblogs.com/fariver/p/6573112.html 动态链接库在Windows中为.dll文件,在linux中为.so文件.以linux平台为例说明py ...

  7. 如何在java程序中调用linux命令或者shell脚本

    转自:http://blog.sina.com.cn/s/blog_6433391301019bpn.html 在java程序中如何调用linux的命令?如何调用shell脚本呢? 这里不得不提到ja ...

  8. Python调用C/C++动态链接库的方法详解

    Python调用C/C++动态链接库的方法详解 投稿:shichen2014 这篇文章主要介绍了Python调用C/C++动态链接库的方法,需要的朋友可以参考下 本文以实例讲解了Python调用C/C ...

  9. 文本分类学习 (十)构造机器学习Libsvm 的C# wrapper(调用c/c++动态链接库)

    前言: 对于SVM的了解,看前辈写的博客加上读论文对于SVM的皮毛知识总算有点了解,比如线性分类器,和求凸二次规划中用到的高等数学知识.然而SVM最核心的地方应该在于核函数和求关于α函数的极值的方法: ...

随机推荐

  1. JZOJ5821手机信号

    用set维护,(l,r,v),注意边界,保证了两个端点l,r一定有信号站 增加有三种可能,1.直接加(没有影响),2.将原本的一个区间变成两个 3.将原本的一个区间变成三个 删除有三种情况,1.全包含 ...

  2. Vue+ElementUI: 手把手教你做一个audio组件

    目的 本项目的目的是教你如何实现一个简单的音乐播放器(这并不难) 本项目并不是一个可以用于生产环境的element播放器,所以并没有考虑太多的兼容性问题 本项目不是ElementUI的一个音频插件,只 ...

  3. 【Codeforces Round #422 (Div. 2) C】Hacker, pack your bags!(hash写法)

    接上一篇文章; 这里直接把左端点和右端点映射到vector数组上; 映射一个open和close数组; 枚举1..2e5 如果open[i]内有安排; 则用那个安排和dp数组来更新答案; 更新答案完之 ...

  4. COGS——T2084. Asm.Def的基本算法

    http://cogs.pro/cogs/problem/problem.php?pid=2084 ★☆   输入文件:asm_algo.in   输出文件:asm_algo.out   简单对比时间 ...

  5. .Net商品管理(注释,百度,提问,对比,总结)

    管理控制器 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sys ...

  6. 获取windows版本信息的做法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 个人不建议用 GetVersion 或GetVersionEx 之类的 API 来获取系统版本号.注意微软也说过,这个 ...

  7. react 组件使用的小记第一天

    //定义一个子组件 var Child = React.createClass({ getInitialState: function() { return {liked: false}; }, ha ...

  8. 《三》build 快速创建模块

    一.将build.php文件复制一份放在 application目录下 二.修改build.php文件代码 <?php return [ 'home' => [ //需要生成的目录 '__ ...

  9. MVC权限验证过滤器

    Action属性,权限设定属性   [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] ...

  10. rm---删除目录huo文件

    rm命令可以删除一个目录中的一个或多个文件或目录,也可以将某个目录及其下属的所有文件及其子目录均删除掉.对于链接文件,只是删除整个链接文件,而原有文件保持不变. 注意:使用rm命令要格外小心.因为一旦 ...