简体   繁体   English

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

[英]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:发生了什么:

  1. You created the object (behind the scenes, Python allocated some memory)您创建了对象(在幕后, Python分配了一些内存)
  2. You called free on the object allocated by Python (which is wrong, not to mention that you also crossed the .dll boundary)你在Python分配的对象上调用了free (这是错误的,更不用说你也越过了.dll边界)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM