Linux下c函数dlopen实现加载动态库so文件代码举例

dlopen()是一个强大的库函数。该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了。可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现。它需要两个参数:一个文件名和一个标志。文件名就是一个动态库so文件,标志指明是否立刻计算库的依赖性。如果设置为 RTLD_NOW 的话,则立刻计算;如果设置的是 RTLD_LAZY,则在需要的时候才计算。另外,可以指定 RTLD_GLOBAL,它使得那些在以后才加载的库可以获得其中的符号。当库被装入后,可以把 dlopen() 返回的句柄作为给 dlsym() 的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。由 www.169it.com 搜集整理

在dlopen()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。

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库)

具体代码举例如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22


#include "stdio.h"

#include <dlfcn.h>

int 
main(
int 
argc,
char 
*argv[])

{

    
char 
module_name[1024]={
"./test_module.so"
};

    
char 
*error=NULL;

    
void 
*module_handle = dlopen(module_name, RTLD_NOW);

    
if
(module_handle == NULL)

    
{

      
error = dlerror();

      
char 
tp[1024] = {0};  

      
snprintf(tp, 256,

     
"Load module \"%s\" error: %s\n"
,

     
module_name, error);    

      
printf
(
"%s"
,tp);

      
return 
1;

    
}
else

    
{

        
printf
(
"Load module[%s] success!\r\n"
,module_name);

    
}

    
return 
1;

}

时间: 2024-10-05 04:58:20

Linux下c函数dlopen实现加载动态库so文件代码举例的相关文章

Ubuntu linux设置从当前目录下加载动态库so文件

linux的excutable在执行的时候缺省是先搜索/lib和/usr/lib这两个目录,然后按照ld.so.conf里面的配置搜索绝对路径,linux缺省是不会在当前目录搜索动态库的.windows加载动态库的时候,缺省是首先加载本地目录下的动态库,然后再搜索windows/system和windows/system32目录. windows的动态库搜索顺序,虽然有可能会造成潜在的混乱,但是对于开发和测试无疑是比较方便的,尤其是debug和release版本的动态库需要经常切换进行测试的时候

Java 加载动态库 dll 文件

不知道具体原理,但是,加载 dll 文件时,带路径或者更改 dll 文件的名字,都会报错.虽然库记载成功了,但是处女座认为这不可接受.于是有了这个解决方案. 在根目录为库创建软连接,然后使用 system.loadLibrary(“libname”) 来加载.事实证明,它时认软连接的. 上代码: import com.seapine.surroundscm.api.*; import java.lang.UnsupportedOperationException; import java.lan

【转载】cocos2dx 中 Android NDK 加载动态库的问题

原文地址:http://blog.csdn.net/sozell/article/details/10551309 cocos2dx 中 Android NDK 加载动态库的问题 闲聊 最近在接入各个平台的SDK,遇到了不少问题,也从中了解了不少知识,之前一直觉得没啥好写的,毕竟做了4个月的游戏开发,也没有碰上什么真正的大问题,cocos2dx的引擎包得也很好,能让人把大部分时间都关注在游戏逻辑.效果的处理上,当然,之前的libevent还是小坑一下,但是和后来遇到的相比,也算不上什么了. 我最

LoadLibrary加载动态库失败

LoadLibrary加载动态库失败的可能原因以及解决方案: (1)dll动态库文件路径不对.此场景细分为以下几种情况: 1.1 文件路径的确错误.比如:本来欲加载的是A文件夹下的动态库a.dll,但是经过仔细排查原因,发现a.dll动态库竟然被拷贝到B文件夹下去了. 若真遇到这种低级错误,建议你找个没人的墙角蹲下用小拇指逆时针划圈圈去吧... 1.2 实参传值错误.比如:实参类型为LPCWTR,经常都会因为字符串转换导致实参事与愿违. 网上的经验总结实例.某程序员经过一番周折后通过以下语句调用

macOS下加载动态库dylib报&quot;code signature invalid&quot;错误的解决办法

一.现象描述 在macOS上搞开发也有一段时间了,也积攒了一定的经验.然而,今天在替换工程中的一个动态库时还是碰到了一个问题.原来工程中用的是一个静态库,调试时发现有问题就把它替换成了动态库.这本来没什么值得一说,可工程编译完后打包测试时发现,不论怎么搞程序都加载不起来.毫无疑问,这是新替换的动态库带来的问题. 二.解决办法 于是尝试打开日志文件看看有什么发现吧: 根据上面的日志文件提示,动态库加载的时候失败了.原因为:code signature invalid.这就奇了个怪了,以前都没碰到类

linux c++ 加载动态库常用的三种方法

链接库时的搜索路径顺序:LD_LIBRARY_PATH --> /etc/ld.so.conf --> /lib,/usr/lib 方法1. vi .bash_profile    设置环境变量LD_LIBRARY_PATH并导出 另: LD_LIBRARY_PATH:启动时连接共享函数库,执行时打开动态函数库首先搜索的路径. LD_DEBUG:显示运行时的信息,如符号寻找和绑定,重定向,执行等等. 方法2.  a)直接在/etc/ld.so.conf 里添加库路径 b)新建文件,后缀为.co

Android 网络加载动态库 .so

这几天做项目时遇到一个问题,共17M的Apk,仅两个.so文件就占到14M,就尝试着用户安装完app之后,根据用户需要再加载.so文件,找了之后,方法倒不复杂. 1. .so文件的网络下载部分就不展示, 2. .so文件存放路径:一般建议存放在 data/data/<packageName>/路径下,代码如下: //getFileDir() :/data/data/<packageName>/file/ File file2 = new File(getFilesDir(), &q

cmake中设置ELF文件加载动态库的位置

1. 三个文件 1. world.c #include<stdio.h> void world(void) { printf("world.\n"); } 2. hello.c #include <stdio.h> void world(void); void hello(void) { printf("hello\n"); world(); } 3. main.c void main(void) { hello(); } 2. 编译动态库

Maven工程webinfo下面的JSP页面无法加载.js、.css文件的解决方案

--下面是我的工程路径 --我jsp的写法 -----启动工程,访问js文件的路径是这样的, href="http://localhost:8080/activiti/css/public.css" 怎么看都没毛病.但是提示404找不到. 所以判断是因为访问被拦截住了.最后分析查找得知,是因为在web.xml缺少了SpringMVC拦截设置. -----下面这段代码来源于其他博客转载 通过在web.xml中添加如下设置后,问题的得以解决: 注意: 下面这段代码,要写在引入springM