How to use malloc and free with python ctypes? How to use malloc and free with python ctypes? python python

How to use malloc and free with python ctypes?


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)#endifstruct 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 ctypesclass 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])