什么是静态库和动态库, 看一篇博客
http://www.cnblogs.com/skynet/p/3372855.html
现在,我们首先生成.so文件
首先, 我们写一个a.c文件
1
2
3
4
5
6
7
8
9
|
#include <stdio.h> void show() { printf ( "this is a test
" ); } int add( int a, int b) { return a + b; } |
然后输入命令
1
|
gcc a.c -fPIC -shared -o a.so |
在当前目录下会产生一个a.so文件
其中 -fPIC是position independent code(位置无关代码)的意思
-shared是产生一个可以与其他对象连接来形成一个可执行文件的共享对象的一个参数
首先, python中调用.so库
1
2
3
4
5
6
7
|
from ctypes import cdll cur = cdll.LoadLibrary( './a.so' ) cur.show() print cur.add( 1 , 2 ) |
结果如下
1
2
|
hello, world! 3 |
然后,在C语言中调用.so文件
首先看一组API
1
2
3
4
5
|
#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文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/** #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
" , fun1(1, 2)); dlclose(foo); return 0; } |
然后编译命令
1
|
gcc main.c -ldl |
输出结果:
1
2
|
hello, world! 3 |