1. 程式人生 > >C/C++:多程序使用dlopen、dlsym、dlclose裝載動態庫

C/C++:多程序使用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://blog.csdn.net/ostar_liang/article/details/14422423?utm_source=copy