我尝试使用ctypes为C库编写Python包装器。 到目前为止,我有:
C.h
typedef struct
{
int erorrCode;
char * Key;
} A;
#ifdef __cplusplus
extern "C" {
#endif
EXPORT void __stdcall DestroyA(A &input);
#ifdef __cplusplus
}
#endif
C.cpp
EXPORT void __stdcall DestroyA(A &input)
{
delete []input.Key;
}
Python.py
import sys
import ctypes
class A(ctypes.Structure):
_fields_ = [
("erorrCode", ctypes.c_int),
("Key", ctypes.c_char_p)]
try:
libapi = ctypes.cdll.LoadLibrary('./lib.so')
except OSError:
print("Unable to load RAPI library")
sys.exit()
DestroyA = libapi.DestroyA
libapi.DestroyA.argtypes = [ctypes.POINTER(A)]
libapi.DestroyA.restype = None
a = A(1,b'random_string')
DestroyA(ctypes.byref(a)) #!!!here is segmentation fault
那么,如何解决细分错误?
注意:只要有一种方法可以在Python端进行修复,我就无法在C ++端更改代码。
答案 0 :(得分:1)
列出[Python.Docs]: ctypes - A foreign function library for Python。
您在这里 未定义的行为 ( UB )。
Python 为其对象内置了内存管理,包括 CTypes 对象。
因此,每次对象( PyObject 基本上是任何东西-包括 Python int ), Python 在后台调用 malloc 函数家族之一,以分配内存。相反,当对象被破坏时(手动或由 GC 破坏),将调用 free 。
发生了什么事
您仅需在分配的指针上调用免费 。这样的例子之一:[SO]: python: ctypes, read POINTER(c_char) in python (@CristiFati's answer)。
如果您想摆脱对象(从而释放它使用的内存),请让 Python 为您完成:
del a
其他说明:
您正在将 __ stdcall 函数与 ctypes.CDLL 一起使用。同样,这是 UB (在 32bit 上)。使用“常规”调用约定( __ cdecl )
您正在传递参考。那是 C ++ 特有的(尽管它只是一个 const ptr )。要与 C 兼容,请使用:
EXPORT void destroyA(A *pInput);