動態庫(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
測試截圖: