天天看點

Python 和 C 語言中調用.so動态庫

什麼是靜态庫和動态庫, 看一篇部落格

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
           

  

轉載于:https://www.cnblogs.com/spxcds/p/5345345.html