我一直在寻找在Python中分配缓冲区的方法,并使用Python ctypes库将其安全地传递给C.
作为第一步,我实现了一个回调来分配缓冲区,函数类型为CFUNCTYPE(c_long, POINTER(c_void_p), c_long)
。
版本1,使用CRT malloc
:
def alloc(buf, size):
print type(buf)
print "allocating string of size-> ", size
buf[0] = vcrt_dll.malloc(size)
return 0
版本2,使用create_string_buffer
:
def string_allocator(buf, size):
print type(buf)
print "allocating string of size-> ", size
buf[0] = create_string_buffer(size)
return 0
我使用下面的代码将指针传递给C. TryAlloc
是一个为Python调用者填充消息的C函数。
C代码:
long TryAlloc(char **buf)
{
long size(256); // magic number !!!
allocator((void **)buf, size);
ZeroMemory(*buf, size);
char msg[] = "hello world";
strncpy_s(*buf, size, msg, strlen(msg));
return 0;
}
Python代码:
def try_alloc():
buf = c_char_p()
sample_dll.TryAlloc(byref(buf))
print buf.value
使用malloc
时,这样可以正常工作,但我需要为分配的缓冲区手动调用free
。当我使用字符串缓冲区替代时,它在Python中引发以下错误:
TypeError: incompatible types, c_char_Array_100 instance instead of c_void_p
我看到其他一些线程正在讨论相同的问题(例如,Calling python from C++, through callback, with variable buffer),但我无法找到适当的解决方案。有人可以提出一个干净的方法来实现这个吗?
答案 0 :(得分:0)
ctypes
正试图阻止您以更严肃的方式破坏您的程序。返回的对象create_string_buffer
拥有它指向的缓冲区,并且当python对象的引用计数达到0时,期望释放此缓冲区。如果您要手动释放此内存,则程序稍后会导致分段错误python对象试图释放它指向的缓冲区。实际上,您不应该尝试释放ctypes
模块分配的任何内存。例如:
i = c_int(10)
p = pointer(i)
vcrt_dll.free(p) # error
您应该手动释放内存的唯一时间是您正在使用的C库返回的堆内存(例如vcrt_dll.malloc
)。