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])