一,python与C类型对应关系
最左边一列的ctypes type,以替代C库中的各种类型。
二,不带参数的调用
1,target.c
#include <stdio.h>
void hello_world(){
printf("hello downey!!\r\n");
}
2,执行命令编译动态连接库文件
gcc -shared -o libtarget.dll target.c
linux:
gcc --shared -fPIC -o target.c libtarget.so
windows:
gcc -shared -o libtarget.dll target.c
3,test.py
import ctypes
if __name__ == '__main__':
test = ctypes.windll.LoadLibrary("./libtarget.dll")
test.hello_world()
4,输出
hello downey!!
三,带参数的调用
1,target.c
#include <stdio.h>
char add(int a, int b){
return a + b;
}
char mul(int a, int b){
return a * b;
}
2,执行编译命令
gcc -shared -o libtarget.dll target.c
3,test.py
from ctypes import *
if __name__ == '__main__':
# windll.LoadLibrary("./libtarget.dll") # woinows应该用windll ,但用cdll在windows下测测试也没问题。
test = cdll.LoadLibrary("./libtarget.dll") # linux 用cdll
test.add.restype = c_int
test.mul.restype = c_int
c = test.add(48,22)
print(type(c))
print(c)
d = test.mul(48, 22)
print(d)
4,输出
<class 'int'>
70
1056
四,结构体数据格式
1,target.c
#include <stdio.h>
#include <string.h>
typedef struct{
char *ptr;
float f;
char array[10];
}target_struct;
target_struct* hello_world(target_struct* target){
static char temp = 0x30;
target->ptr = &temp;
target->f = 3.1;
memset(target->array,1,sizeof(target->array));
return target;
}
2,执行编译命令
gcc -shared -o libtarget.dll target.c
3,test.py
from ctypes import *
# 声明一个和结构体数据对应的数据结构类
# _fields_是字典类型,key要与C库中结构体相对应,value则是指定相应类型
class test_struct(Structure):
_fields_ = [('ptr', c_char_p),
('c', c_float),
('array', c_char * 10)]
if __name__ == '__main__':
test = windll.LoadLibrary("./libtarget.dll")
# 构造一个对应C中结构体的类,可以传入对应参数进行构造。
struct = test_struct(c=0.5)
#指定返回值类型为test_struct指针类型,这里的类型由POINTER()修饰,表示是指针类型
test.hello_world.restype = POINTER(test_struct)
# 调用hello_world()函数,传入struct类,pointer(struct)就是将struct转为指针类型实例。因为在C中的接口就是传入target_struct类型,返回target_struct类型,所以ret_struct也是target_struct*类型
ret_struct = test.hello_world(pointer(struct))
# 打印函数返回值,查看执行结果。对于一个指针类型的变量,如果我们要获取它的值,可以使用.contents方法
print(ret_struct.contents.ptr)
print(ret_struct.contents.c)
4,输出
b'0'
3.0999999046325684
五,参数传入函数引用,c调用python函数
1,target.c
#include <stdio.h>
#include <string.h>
typedef void (*callback)(int);
void func(callback c1,callback c2,int p1,int p2){
c1(p1);
c2(p2);
}
2,执行编译命令
gcc -shared -o libtarget.dll target.c
3,test.py
from ctypes import *
def test_callback1(val):
print("I'm callback1")
print(val)
def test_callback2(val):
print("I'm callback2")
print(val)
if __name__ == '__main__':
test = windll.LoadLibrary("./libtarget.dll")
CMPFUNC = CFUNCTYPE(None, c_int)
cbk1 = CMPFUNC(test_callback1)
cbk2 = CMPFUNC(test_callback2)
test.func(cbk1, cbk2, 1, 2)
4,输出
I'm callback1
1
I'm callback2
2
windos 安装gcc:
Mingw快捷安装教程 并完美解决出现的下载错误:The file has been downloaded incorrectly_mingw the file has been downloaded incorrectly-CSDN博客
参考:
python代码用c语言封装_python调用C语言接口-CSDN博客