之前用过这三个函数一直没时间整理一下。今天抽时间整理一下。
1、函数简介
dlopen
基本定义
功能:打开一个动态链接库
包含头文件:
#include <dlfcn.h>
函数定义:
void * dlopen( const char * pathname, int mode );
函数描述:
在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。
mode:分为这两种
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
RTLD_LOCAL
RTLD_GLOBAL 允许导出符号
RTLD_GROUP
RTLD_WORLD
返回值:
打开错误返回NULL
成功,返回库引用
编译时候要加入 -ldl (指定dl库)
dlsym()
功能:
根据动态链接库操作句柄与符号,返回符号对应的地址。
包含头文件:
#include <dlfcn.h>
函数定义:
void*dlsym(void* handle,const char* symbol)
函数描述:
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数或全局变量的名称。
dlclose()
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
上述都是摘抄,总结为链接的时候需要用到dl库,编译的时候需要加上dlfcn.h头文件。才能保证编译不会报错。
2、生成动态库
hello.c函数原型:
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
typedef struct
{
const char *module;
int (*GetValue)(char *pszVal);
int (*PrintfHello)();
} hello_ST_API;
int GetValue(char *pszVal)
{
int retval = -1;
if (pszVal)
retval = sprintf(pszVal, "%s", "123456");
printf("%s, %d, pszVer = %s\n", __FUNCTION__, __LINE__, pszVal);
return retval;
}
int PrintfHello()
{
int retval = -1;
printf("%s, %d, hello everyone\n", __FUNCTION__, __LINE__);
return 0;
}
const hello_ST_API Hello =
{
.module = "hello",
GetValue,
PrintfHello,
};
编译的时候用指令:
gcc -shared -o hello.so hello.c
上面的函数是用一个全局结构体hello来指向。在dlsym定义中说不仅可以获取函数的地址,还可以获取全局变量的地址。所以此处是想通过dlsym来获取全局变量的地址。好处自己慢慢体会。
3、dlopen代码
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
typedef struct {
const char *module;
int (*GetValue)(char *pszVal);
int (*PrintfHello)();
} hello_ST_API;
int main(int argc, char **argv)
{
hello_ST_API *hello;
int i = 0;
void *handle;
char psValue[20] = {0};
handle = dlopen(“库存放的绝对路径,你可以试试相对路径是不行的", RTLD_LAZY);
if (! handle) {
printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
return -1;
}
dlerror();
hello = dlsym(handle, "Hello");
if (!hello) {
printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
return -1;
}
if (hello && hello->PrintfHello)
i = hello->PrintfHello();
printf("%s, %d, i = %d\n", __FUNCTION__, __LINE__, i);
if (hello && hello->GetValue)
i = hello->GetValue(psValue);
if (hello && hello->module)
{
printf("%s, %d, module = %s\n", __FUNCTION__, __LINE__, hello->module);
}
dlclose(handle);
return 0;
}
编译指令:gcc -o test hello_dlopen.c -ldl
运行./test结果如下。
PrintfHello, 27, hello everyone
main, 36, i = 0
GetValue, 19, pszVer = 123456
main, 42, module = hello
可以看到结果正常出来了。
看到没用?dlsym找到全局结构体hello后,可以直接用这个全局结构体指针来使用库里面的函数了,因为我们有时候提供的库不仅仅是一个两个函数的,一般的一个库都会存在多个函数,用这种方式就可以直接使用了。
不然找函数名称的话要写多少个dlsym啊?
标签:__,include,handle,函数,dlsym,int,linux,dlclose,hello From: https://blog.51cto.com/u_16081664/6224148