How to use malloc and free with python ctypes?

前端 未结 1 1383
醉酒成梦
醉酒成梦 2020-12-25 08:57

I have a function in my C library, say runsim() which takes pointer to struct repdata as one of the arguments, where struct repdata is

相关标签:
1条回答
  • 2020-12-25 09:14

    You can allocate buffers using ctypes and assign them to the pointers. Once the Python ctypes objects have no references they will be freed automatically. Here's a simple example (with a Windows DLL...don't have a Linux machine handy, but the idea is the same) and a Python wrapper.

    create_string_buffer allocates a writable buffer that can be passed from Python to C that ctypes will marshal as a char*.

    You can also create writable arrays of ctypes types with the syntax:

    variable_name = (ctypes_type * length)(initial_values)
    

    x.h

    #ifdef DLL_EXPORTS
    #define DLL_API __declspec(dllexport)
    #else
    #define DLL_API __declspec(dllimport)
    #endif
    
    struct example {
        char* data;
        int len;          // of data buffer
        double* doubles;
        int count;        // of doubles
    };
    
    DLL_API void func(struct example* p);
    

    x.c

    #include <stdio.h>
    #define DLL_EXPORTS
    #include "x.h"
    
    void func(struct example* p)
    {
        int i;
        strcpy_s(p->data,p->len,"hello, world!");
        for(i = 0; i < p->count; i++)
            p->doubles[i] = 1.1 * (i + 1);
    }
    

    x.py

    import ctypes
    
    class Example(ctypes.Structure):
    
        _fields_ = [
            ('data',ctypes.POINTER(ctypes.c_char)),
            ('len',ctypes.c_int),
            ('doubles',ctypes.POINTER(ctypes.c_double)),
            ('count',ctypes.c_int)]
    
        def __init__(self,length,count):
            self.data = ctypes.cast(ctypes.create_string_buffer(length),ctypes.POINTER(ctypes.c_char))
            self.len = length
            self.doubles = (ctypes.c_double * count)()
            self.count = count
    
        def __repr__(self):
            return 'Example({},[{}])'.format(
                ctypes.string_at(self.data),
                ','.join(str(self.doubles[i]) for i in range(self.count)))
    
    class Dll:
    
        def __init__(self):
            self.dll = ctypes.CDLL('x')
            self.dll.func.argtypes = [ctypes.POINTER(Example)]
            self.dll.func.restype = None
    
        def func(self,ex):
            self.dll.func(ctypes.byref(ex))
    
    d = Dll()
    e = Example(20,5)
    print('before:',e)
    d.func(e)
    print ('after:',e)
    

    Output

    before: Example(b'',[0.0,0.0,0.0,0.0,0.0])
    after: Example(b'hello, world!',[1.1,2.2,3.3000000000000003,4.4,5.5])
    
    0 讨论(0)
提交回复
热议问题