在 Python 中使用 ctypes 模块可以很轻松定义 C 类型的变量,以及调用 C/C++ 函数.
1. 基础类型变量
from ctypes import * def test(): a = c_short(10) b = c_int(20) c = c_long(30) d = c_longlong(40) e = c_float(3.14) f = c_double(3.14) g = c_longdouble(3.14) print(a, a.value) print(b, b.value) print(c, c.value) print(d, d.value) print(e, e.value) print(f, f.value) if __name__ == '__main__': test()
程序输出结果:
c_short(10) 10 c_int(20) 20 c_long(30) 30 c_long(40) 40 c_float(3.140000104904175) 3.140000104904175 c_double(3.14) 3.14
2. 指针类型变量
from ctypes import * def test(): a = c_int(20) # 定义 int 类型指针 b = POINTER(c_int) # 指针指向 a 变量 b = pointer(a) # 打印指针的值 print(b) # 访问指针指向的空间的值 print(b.contents) if __name__ == '__main__': test()
程序输出结果:
<__main__.LP_c_int object at 0x7fb6f826c9c0> c_int(20)
3. Python 调用 C 函数
- 编写 C 函数
- 将 C 函数编译成自己平台的动态库(以 Mac 为例)
- 在 Python 中使用 ctypes 模块调用 C 函数
我们的 C 函数在 test.c 文件,代码如下:
#include <stdlib.h> #include <stdio.h> #include <string.h> void memory_copy(const void* src, void* dst, size_t ele_size, size_t ele_num) { if (NULL == src) { return; } if (NULL == dst) { return; } if (ele_size <= 0 || ele_num <= 0) { return; } char* new_dst = (char *)dst; const char* new_src = (const char *)src; for (int i = 0; i < ele_size * ele_num; ++i) { *new_dst++ = *new_src++; } }
使用下面的命令将其打成 Mac 平台的动态库文件:
gcc -dynamiclib -o libmy.dylib test.c
接下来,在 Python 中调用 C 函数代码如下:
from ctypes import * # 加载动态库 c_obj = CDLL('libmy.dylib') # 由于函数进行的逐字节拷贝, 需要将字符串定为字节类型 src = b'hello world' # 开辟空间字符串长度大小的空间 dst = create_string_buffer(len(src) + 1) # 打印空间的数据 print('dst:', dst.raw) # 打印空间的内容 print('dst:', dst.value) # 调用自定义的C函数实现内存拷贝 c_obj.memory_copy(src, pointer(dst), 1, len(src) + 1) print('dst:', dst.raw) print('dst:', dst.value)