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

  

posted @ 2016-04-01 16:26  spxcds  阅读(9363)  评论(0编辑  收藏  举报