什么是靜態庫和動態庫, 看一篇博客
http://www.cnblogs.com/skynet/p/3372855.html
現在,我們首先生成.so文件
首先, 我們寫一個a.c文件
#include <stdio.h> void show() { printf("this is a test\n"); } int add(int a, int b) { return a + b; }
然后輸入命令
gcc a.c -fPIC -shared -o a.so
在當前目錄下會產生一個a.so文件
其中 -fPIC是position independent code(位置無關代碼)的意思
-shared是產生一個可以與其他對象連接來形成一個可執行文件的共享對象的一個參數
首先, python中調用.so庫
from ctypes import cdll cur = cdll.LoadLibrary('./a.so') cur.show() print cur.add(1, 2)
結果如下
hello, world! 3
然后,在C語言中調用.so文件
首先看一組API
#include <dlfcn.h> void *dlopen(const char *filename, int flag); void *dlsym(void *handle, const char *symbol); int dlclose(void *handle); char *dlerror(void);
下面, 分別解釋這幾個函數
dlopen
dlopen()函數以指定模式打開指定的動態鏈接庫文件,並返回動態鏈接庫的句柄。參數flag有以下兩種常用的值,並且必須指定其一。 RTLD_LAZY:在dlopen返回前,對於動態庫中存在的未定義的變量(如外部變量extern,也可以是函數)不執行解析,就是不解析這個變量的地址。 RTLD_NOW:與上面不同,他需要在dlopen返回前,解析出每個未定義變量的地址,如果解析不出來,在dlopen會返回NULL.
dlsym
dlsym()函數根據動態鏈接庫操作句柄(handle)與符號(symbol),返回符號對應的地址。使用這個函數不但可以獲取函數地址,也可以獲取變量地址。參數的含義如下: handle:由dlopen打開動態鏈接庫后返回的指針; symbol:要求獲取的函數或全局變量的名稱。
dlclose
dlclose()函數用於關閉指定句柄的動態鏈接庫,只有當此動態鏈接庫的使用計數為0時,才會真正被系統卸載。
dlerror
當動態鏈接庫操作函數,如dlopen/dlsym/dlclose//執行失敗時,dlerror()函數可以返回最近的出錯信息,返回值為NULL時表示操作函數執行成功。
C語言用戶需要包含頭文件dlfcn.h才能使用上述API。
然后, 我們新建一個main.c文件
/** #include <dlfcn.h> void *dlopen(const char *filename, int flag); void *dlsym(void *handle, const char *symbol); int dlclose(void *handle); char *dlerror(void); **/ #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main() { void *foo = dlopen("./a.so", RTLD_LAZY); dlerror(); void (*fun)() = dlsym(foo, "show"); int (*fun1)(int, int) = dlsym(foo, "add"); fun(); printf("%d\n", fun1(1, 2)); dlclose(foo); return 0; }
然后編譯命令
gcc main.c -ldl
輸出結果:
hello, world! 3