Ctypes.如何通过引用传递结构



我尝试使用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

发生了什么:

  1. 您创建了对象(在幕后,Python分配了一些内存(
  2. 您在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);
    

相关内容

  • 没有找到相关文章

最新更新