我尝试使用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
那么,如何修复分割错误呢?
注意:我不能更改C++端的代码,只要有办法在Python端修复它。
Listing[Python.Docs]:ctypes-Python的外部函数库。
您在这里有未定义的行为(UB(。
Python为其对象内置内存管理,包括CTypes对象
因此,每当一个对象(基本上是任何东西的PyObject,包括Pythonint(,Python都会调用引擎盖下的一个malloc函数家族来分配内存。相反,当对象被销毁(手动或通过GC(时,会调用free。
发生了什么:
- 您创建了对象(在幕后,Python分配了一些内存(
- 您在Python分配的对象上调用了free(这是错误的,更不用说您还越过了.dll边界(
您只需要在分配的指针上调用free。例如:[SO]:python:ctypes,在python中读取POINTER(c_char((@CristiFati的答案(。
如果你想摆脱这个对象(从而释放它使用的内存(,让Python为你做:
del a
附加备注:
您将__stdcall函数与ctypes.cDL一起使用。同样,这是UB(在32位上(。使用";常规的";调用约定(__cdecl(
你正在传递一个推荐人。这是特定于C++的(尽管它只是常量ptr(。要与C兼容,请使用:
EXPORT void destroyA(A *pInput);