[英]Ctypes. How to pass struct by reference?
I try to write Python wrapper for C library using ctypes.我尝试使用 ctypes 为 C 库编写 Python 包装器。 So far I have:到目前为止,我有:
Ch通道
typedef struct
{
int erorrCode;
char * Key;
} A;
#ifdef __cplusplus
extern "C" {
#endif
EXPORT void __stdcall DestroyA(A &input);
#ifdef __cplusplus
}
#endif
C.cpp cpp
EXPORT void __stdcall DestroyA(A &input)
{
delete []input.Key;
}
Python.py蟒蛇.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
So, how can I fix the segmentation fault error?那么,如何修复分段错误错误?
Note: I cannot change the code on the C ++ side as long as there is a way to fix it on the Python side.注意:只要有办法在 Python 端修复它,我就无法更改 C++ 端的代码。
Listing [Python.Docs]: ctypes - A foreign function library for Python .清单[Python.Docs]: ctypes - Python 的外部函数库。
You have here Undefined Behavior ( UB ).你在这里有未定义的行为( UB )。
Python has builtin memory management for its objects, including CTypes ones. Python为其对象(包括CTypes对象)内置了内存管理。
So, every time an object ( PyObject which is basically anything - including a Python int ), Python invokes one of the malloc functions family under the hood in order to allocate memory.因此,每次对象( PyObject基本上是任何东西 - 包括Python int )时, Python 都会调用内部的malloc函数系列之一以分配内存。 Conversely, when the object is destroyed (manually or by GC ), free is called.相反,当对象被销毁(手动或通过GC )时,会调用free 。
What happened:发生了什么:
You need to call free only on pointers that you allocated .您只需要在您分配的指针上调用free 。 One such example: [SO]: python: ctypes, read POINTER(c_char) in python (@CristiFati's answer) .一个这样的例子: [SO]: python: ctypes, read POINTER(c_char) in python (@CristiFati's answer) 。
If you want to get rid of the object (and thus free the memory that it uses), let Python do it for you:如果你想摆脱这个对象(从而释放它使用的内存),让Python为你做:
del a
Additional remarks:补充说明:
You're using __stdcall functions with ctypes.CDLL .您正在将__stdcall函数与ctypes.CDLL一起使用。 Again, that's UB (on 32bit ).同样,那是UB (在32bit 上)。 Use the "regular" calling convention ( __cdecl )使用“常规”调用约定( __cdecl )
You're passing a reference.你正在传递一个参考。 That's C++ specific (although it's only a const ptr ).那是C++特定的(尽管它只是一个const ptr )。 To be C compatible, use:要与C兼容,请使用:
EXPORT void destroyA(A *pInput);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.