dlopen dlsym dlclose

    xiaoxiao2021-03-25  66

    dlopen、dlsym和dlclose的使用和举例  

      之前用过这三个函数一直没时间整理一下。今天抽时间整理一下。

    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啊?

    转载请注明原文地址: https://ju.6miu.com/read-35521.html

    最新回复(0)