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
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)
#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);
#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);
}
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)
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])