在 Python 中使用 ctypes 模块可以很轻松定义 C 类型的变量,以及调用 C/C++ 函数.
- 基础类型变量 {#title-0} ====================
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
- 指针类型变量 {#title-1} ====================
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)
-
Python 调用 C 函数 {#title-2} ============================
-
编写 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)