Ctypes。如何通过引用传递结构?

时间:2020-03-25 04:48:31

标签: python struct ctypes dynamic-library

我尝试使用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 ++端更改代码。

1 个答案:

答案 0 :(得分:1)

列出[Python.Docs]: ctypes - A foreign function library for Python

您在这里 未定义的行为 UB )。

Python 为其对象内置了内存管理,包括 CTypes 对象。
因此,每次对象( PyObject 基本上是任何东西-包括 Python int ), Python 在后台调用 malloc 函数家族之一,以分配内存。相反,当对象被破坏时(手动或由 GC 破坏),将调用 free

发生了什么事

  1. 您创建了对象(在幕后, Python 分配了一些内存)
  2. 您在 Python 分配的对象上调用了 free (这是错误的,更不用说您还跨越了 .dll 边界)

您仅需在分配的指针上调用免费 。这样的例子之一:[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);
    
相关问题