How to pass a list/array of structs from python to C -
i have c function must callable c , python.
i'm having trouble figuring out how pass python list of c-type structs, each of contains several nested structs, c function.
a single 1 of these structs looks in python:
class station_mm_node(ctypes.structure): _fields_ = [ ("signal", mm_struct), ("noise", mm_struct), ("signalwindowlen", ctypes.c_double), ("metadata", sac_pz) ] and in c:
typedef struct stationmmnode { struct mantlemagstruct *signal; struct mantlemagstruct *noise; double signalwindowlen; sac_pz metadata; } stationmmnode_t; the c function takes array of stationmmnode structs callable as:
double magnitudecompute_mw_mm_event(stationmmnode_t **stationmmarray, int numstations); for instance, can call purely c in:
int testfunc() { stationmmnode_t *node1 = malloc(sizeof(struct stationmmnode)); node1->signalwindowlen = 500; stationmmnode_t *node2 = malloc(sizeof(struct stationmmnode)); node2->signalwindowlen = 100; struct stationmmnode *nodes[2]; nodes[0] = node1; nodes[1] = node2; magnitudecompute_mw_mm_event(nodes, 2); // works! } in python, can create list of nodes looks similar c array of structs:
stationmmnodes = [] ... node = get_stationmmnode() # returns station_mm_node node.signal = mm_signal node.noise = mm_noise node.metadata = sacpolezero stationmmnodes.append(node) ... wrap_lib.magnitudecompute_mw_mm_event(stationmmnodes, numstations) # not work where i've defined argtypes as:
wrap_lib.magnitudecompute_mw_mm_event.argtypes = [ctypes.pointer(station_mm_node), ctypes.c_int ] the model i'm using above (passing ctype pointer c-style struct c function takes pointer struct) seems work fine when passing in pointer single struct, however, pointer array of structs, seems break down. in addition, uncertain of python memory layout list of structs versus array of pointers struct (as c function expecting).
any appreciated!
update: found following link helpful: python ctypes array of structs
i solved problem by: 1. declaring array of pointers struct:
nodearraytype = ctypes.pointer(station_mm_node) * 1024 nodearray = nodearraytype() nstn = 0 2. writing c function join member structs larger struct (=a node) , return pointer struct - stored in nodearray[].
nodearray[nstn] = wrap_libmth.libmth.makenode(node.signal, node.noise, node.metadata) nstn += 1 3. fixing argtype of c function receives pointer struct array:
wrap_libmth.libmth.magnitudecompute_mw_mm_event.argtypes = [ctypes.pointer(ctypes.pointer(station_mm_node)), ctypes.c_int] so ... have working, thing python, feel i'm holding tiger tail don't understand why works , (better) alternatives (e.g., c hack makenode() return pointer station_mm_node struct less satisfactory - better generate struct in python).
Comments
Post a Comment