python 调用 os库

来源:互联网 发布:青藏铁路灵异事件知乎 编辑:程序博客网 时间:2024/06/03 20:11


注意:在使用c++写动态库时需要要在声明函数时前面加上extern "C" 或 extern "C"{....}方式

// 因为使用g++编译时函数名会改变,比方print_msg(const char*)// 会编译成函数名 print_msg_char,这会导致python调用这个函数的时候// 找不到对应的函数名,这有加了 extern "C",才会以C语言的方式进行// 编译,这样不会改变函数名字
生成出来的so库可用nm或nm -g命令查看动态库中包含的模块 T标识表示接口函数 B表示全局变量


我们首先生成.so文件

首先, 我们写一个a.c文件

1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
void show() {
    printf("this is a test\n");
}
 
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(12)

 结果如下

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)(intint) = dlsym(foo, "add");
    fun();
    printf("%d\n", fun1(1, 2));
    dlclose(foo);
 
    return 0;
}

  

然后编译命令

1
gcc main.c -ldl

  输出结果:

1
2
hello, world!
3
0 0
原创粉丝点击