Python ctypes definition for c struct

I am trying to call some c code generated by the Matlab encoder. Matlab uses a c-structure called emxArray to represent matrices (described here: http://www.mathworks.co.uk/help/fixedpoint/ug/c-code-interface-for-unbounded-arrays-and-structure- fields.html ).

struct emxArray_real_T { double *data; int *size; int allocatedSize; int numDimensions; boolean_T canFreeData; }; 

I have little ctypes experience and am trying to create an equivalent structure that I can use to pass vectors back and forth for functions defined in c.so

This is where I am still in python ...

 class EmxArray(ctypes.Structure): """ creates a struct to match emxArray_real_T """ _fields_ = [('data', ctypes.POINTER(ctypes.c_double)), ('size', ctypes.POINTER(ctypes.c_int)), ('allocatedSize', ctypes.c_int), ('numDimensions', ctypes.c_int), ('canFreeData', ctypes.c_bool)] 

However, if I define this:

 data = (1.1, 1.2, 1.3, 1.4) L = len(data) x = EmxArray() x.data = (ctypes.c_double * L)(*data) x.data = (ctypes.c_int * 1)(L) 

it works

 print len(x.data[:L]) for v in x.data[:L]: print v 

Edit: I tidied up and accepted Roland's suggestion and can extract data using

 data_out = x.data[:L] 

I need to further explore if I can successfully use this structure to send and receive data from c code.

Decision

The implementation of the ctypes structure suggested by Roland didn't work - the return values ​​were garbage, I never knew why when I was chasing the python-based lilbil response implementation. I accepted this answer as it was the closest ...

I will write down my decision here, as this can save someone who spends as much time as I have.

Firstly, I created a simple matlab function, which in itself multiplies each element of the function and uses an encoder to compile this with .so. This is imported into python using ctypes. The code is as follows:

 import ctypes LIBTEST = '..../dll/emx_test/' EMX = ctypes.cdll.LoadLibrary(LIBTEST + 'emx_test.so') init = EMX.emx_test_initialize() # Create a data structure to hold the pointer generated by emxCreateWrapper... class Opaque(ctypes.Structure): pass # make some random data to pass in data_in = [1., 2., 4., 8., 16.] L = len(data_in) # create an empty array of the same size for the output data_ou = [0] * L # put this in a ctypes array ina = (ctypes.c_double * L)(*data_in) oua = (ctypes.c_double * L)(*data_ou) # create a pointer for these arrays & set the rows and columns of the matrix inp = ctypes.pointer(ina) oup = ctypes.pointer(oua) nrows = ctypes.c_int(1) ncols = ctypes.c_int(L) # use EMX.emxCreateWrapper_real_T(double *data, int rows, int cols) to generate an emx wrapping the data # input arg types are a pointer to the data NOTE its not great to have to resize the ctypes.c_double but cant see another way EMX.emxCreateWrapper_real_T.argtypes = [ctypes.POINTER(ctypes.c_double * L), ctypes.c_int, ctypes.c_int] # a pointer to the emxArray is returned and stored in Opaque EMX.emxCreateWrapper_real_T.restype = ctypes.POINTER(Opaque) # use emxCreateWrapper in_emx = EMX.emxCreateWrapper_real_T(inp, nrows, ncols) ou_emx = EMX.emxCreateWrapper_real_T(oup, nrows, ncols) # so now we have to emx created and have pointers to them we can run the emx_test # emx test looks like this in matlab # # function res = emx_test ( in ) # res = in .* in; # end # # so basically it multiplies each element of the matrix by itself # # therefore [1., 2., 4., 8., 16.] should become [1., 4., 8., 64., 256.] EMX.emx_test(in_emx, ou_emx) # and voila...that what we get print 'In: ', ina[:L] print 'Out:', oua[:L] 

Output:

 In: [1.0, 2.0, 4.0, 8.0, 16.0] Out:[1.0, 4.0, 16.0, 64.0, 256.0] 

Thank you all for your time and suggestions.

+7
python ctypes matlab-coder
source share
2 answers

I'm not well versed in the Python-C interface, so I suggest being less than ideal. I assume that the probability of failure is that x->data never initialized, and the memory it points to is not allocated.

The approach I used when interacting with MATLAB Coder, generated code from other languages ​​in the presence of emxArray arguments, is to write a C interface function that provides a simpler API. This reduces the burden of having to create emxArray in another environment (Android Java in my particular case). If the generated function foo accepts and returns a 2-D double array, then the following may work:

 void foo(double *x, int *szx, double **y, int *szy); 

This function will take a pointer to the input and its size and provide a pointer to the output and its size. The implementation will look something like this:

 void foo(double *x, int *szx, double **y, int *szy) { emxArray_real_T *pEmx; emxArray_real_T *pEmy; /* Create input emxArray assuming 2-dimensional input */ pEmx = emxCreateWrapper_real_T(x, szx[0], szx[1]); /* Create output emxArray (assumes that the output is not */ /* written before allocation occurs) assuming 2-D output */ pEmy = emxCreateWrapper_real_T(NULL, 0, 0); /* Call generated code (call foobar_initialize/terminate elsewhere) */ foobar(pEmx, pEmy); /* Unpack result - You may want to MALLOC storage in *y and */ /* MEMCPY there alternatively */ *y = pEmy->data; szy[0] = pEmy->size[0]; szy[1] = pEmy->size[1]; /* Clean up any memory allocated in the emxArrays (eg the size vectors) */ emxDestroyArray_real_T(pEmx); emxDestroyArray_real_T(pEmy); } 

You can simply call this function from Python and pass the necessary data as needed.

My other answer contains more details on the emxArray_* functions found in foobar_emxAPI.h .

+2
source share

Just create a pointer, then assign data;

 import ctypes class EmxArray(ctypes.Structure): """ creates a struct to match emxArray_real_T """ _fields_ = [('data', ctypes.POINTER(ctypes.c_double)), ('size', ctypes.POINTER(ctypes.c_int)), ('allocatedSize', ctypes.c_int), ('numDimensions', ctypes.c_int), ('canFreeData', ctypes.c_bool)] data = (1.3, 3.5, 2.7, 4.1) L = len(data) e = EmxArray() e.data = (ctypes.c_double * L)(*data) e.size = (ctypes.c_int * 1)(L) # et cetera 
+5
source share

All Articles