动态库(libxxx.so)一种调用方式是在编译的时候的时候指定库名 -lxxx,另一种调用方式是通过dlopen在程序里加载动态库,然后调用相关接口。相关接口比较简单,包括打开动态库,解析库里提供的symbol(函数或者变量),关闭动态库引用计数。
编译的时候加上-ldl(指定dl库)
头文件
#include <dlfcn.h>
/**
* 加载指定的动态库并返回动态库的句柄。如果参数filename为NULL
* 则返回的句柄就是main program.如果加载的库又依赖其它的动态库
* 则这些库会自动被链接器加载。
* flags有如下选项,可以ORed方式选择多个
* RTLD_LAZY : 在dlopen返回前,对于动态库中的未定义的符号不执行解析(只对函数引用有效,对于变量引用总是立即解析)。
* RTLD_NOW : 需要在dlopen返回前,解析出所有未定义符号,如果解析不出来,在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......
* RTLD_GLOBAL:动态库中定义的符号可被其后打开的其它库解析。
* RTLD_LOCAL:动态库中定义的符号可被其后打开的其它库解析。
* 成功返回非NULL句柄,失败返回NULL;
*/
void *dlopen(const char *filename, int flags);
/**
* 减少共享库句柄的引用计数,如果系统中没有其它引用的地方,则卸载该库。
* 成功返回0,失败返回非零值。
*/
int dlclose(void *handle);
/**
* 从dlopen返回的句柄中查找指定的符号并返回地址,
* 成功返回该符号地址,失败返回NULL。
*/
void *dlsym(void *handle, const char *symbol);
libHelloWorld.so实现代码:
//实现文件 HelloWorld.c
/**
* 简单动态库文件使用
*/
#include "HelloWorld.h"
void hello(void)
{
printf("Hello World \r\n");
return ;
}
//头文件 HelloWorld.h
#include <stdio.h>
void hello(void);
dlopen测试程序:
/**
* linux平台 dlopen接口调用动态库简单例子
*/
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
void main()
{
void *handle;
void (*hello)(void);
/* 加载libHelloWorld.so */
handle = dlopen("libHelloWorld.so", RTLD_LAZY);
if (!handle)
{
printf("open libHelloWorld.so fail\r\n");
return;
}
/* 引用库提供的symbol,可以是变量也可以是函数 */
hello = dlsym(handle, "hello");
if ( !hello )
{
printf("open symbol fail\r\n");
dlclose(handle);
return;
}
/* 调用库函数 */
hello();
/* 释放库的引用计数 */
dlclose(handle);
return;
}
Makefile:
#
# Linux dlopen接口调用动态库简单例子
#
# -shared 指定生成动态链接库
# -fPIC :表示编译为位置独立的代码,用于编译共享库
dynlib:
gcc -shared -fPIC -o libHelloWorld.so HelloWorld.c
cp -rf libHelloWorld.so /usr/lib/
#使用dlopen接口需要在编译的时候加上-ldl选项
dllib:
gcc -o dllib dl_call_lib.c -ldl
clean:
rm -rf *.o *.so demoapp
测试截图: