通过ctypes从C线程调用时malloc失败

0 投票
2 回答
857 浏览
提问于 2025-04-17 12:25

我正在使用Python的CTypes来连接一个共享库;我在这个库中注册了一个回调函数,这个回调是在库自己创建的线程中被调用的。我发现,如果我在回调函数中调用libc.malloc()libc = cdll.LoadLibrary('libc.so.6')),它返回的值是错误的。不是NULL,而是一个地址,如果我试图使用这个地址,就会导致程序崩溃。

有没有人能告诉我这可能是什么原因,或者说他们也以同样的方式调用malloc(),并且一切正常。

2 个回答

0

下面的代码在Windows上可以正常运行。在Linux上应该也差不多。它甚至可以在32位系统上运行,而不需要明确设置argtypes/restype这些属性。

from ctypes import *

crt = CDLL('msvcrt')
malloc = crt.malloc
malloc.argtypes = [c_size_t]
malloc.restype = c_void_p
free = crt.free
free.argtypes = [c_void_p]
free.restype = None

n = cast(malloc(10),POINTER(c_ubyte))
for i in range(10):
    print '{:02X}'.format(n[i]),
free(n)

因为你提到了回调函数,所以要确保在使用回调的整个过程中都保持对它的引用。这意味着不要像这样调用它:

set_callback(CFUNCTYPE(...)(callback_func))

CFUNCTYPE对象在设置回调后就会被销毁。正确的做法是:

@CFUNCTYPE(...)
def callback_func(...)
    ...

set_callback(callback_func)

这种装饰器的写法会在模块(或者类,如果是方法的话)存在的期间,把Python的函数对象替换成ctypes的回调对象。

1

你有没有正确地标注malloc调用,让ctypes知道它应该返回指针而不是整数?(如果你是在64位的机器上工作,这一点尤其重要。)

撰写回答