Sto provando a chiamare un codice c generato dal codificatore Matlab. Matlab usa una struttura c chiamata emxArray per rappresentare le matrici (documentata qui: http://www.mathworks.co.uk/help/fixedpoint/ug/c-code-interface-for-unbounded-arrays-and-structure-fields.html).Definizione ctypes Python per c struct
struct emxArray_real_T
{
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
ho poco ctypes esperienza e sto lottando per creare una struct equivalente che posso utilizzare per passare vettori avanti e indietro per le funzioni definite nel c .so
qui è dove ho ottenuto finora in pitone ...
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)]
Tuttavia, se mi definiscono questa:
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)
questo allora funziona
print len(x.data[:L])
for v in x.data[:L]: print v
Edit: Ho riordinato e adottato il suggerimento di Roland e può estrarre i dati utilizzando
Ho bisogno di indagare ulteriormente per vedere se posso usare con successo questo struct per passare e ricevere dati dal codice c.
Soluzione
Attuazione del struct ctypes come suggerito da Roland non ha funzionato - i valori restituiti erano spazzatura, non ho mai lavorato fuori perché come ho perseguito un'implementazione basata pitone della risposta di lilbil. Ho accettato quella risposta perché era la più vicina ...
Documenterò qui la mia soluzione perché potrebbe salvare qualcun altro perdendo tutto il tempo che ho.
In primo luogo ho generato una semplice funzione MATLAB che moltiplica ciascun elemento di una funzione da solo & utilizzato il codificatore per compilarlo a un c .so. Questo è importato in python usando i ctype. Il codice è il seguente ...
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's 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's what we get
print 'In: ', ina[:L]
print 'Out:', oua[:L]
uscita:
In: [1.0, 2.0, 4.0, 8.0, 16.0]
Out:[1.0, 4.0, 16.0, 64.0, 256.0]
Grazie a tutti per il vostro tempo & suggerimenti.
Mi sembra che probabilmente non sono necessarie le parti 'sz' e' ... * sz)) 'della classe 'EmxArray'. –
La ragione per cui l'ho fatto è che i dati saranno una matrice sarebbe meglio se potessi consentire comunque un array di dimensioni variabili. –