Passing Array of Objects OR Array of Arrays Between Python & C++ Library -
i've extern "c"
declaration of c++ function, compiled part of shared library on ubuntu, getvphistory
void getvphistory(actorpos allpostions[], uint numact, uint numdim, uint numstate) { uint actordimpaircount = numact * numdim; uint actordimpairindex = 0; float val = 1.0; (uint actor = 0; actor < numact; ++actor) { (uint dim = 0; dim < numdim; ++dim) { actorpos *ap = &allpostions[actordimpairindex]; ++actordimpairindex; ap->actor = actor; ap->dim = dim; ap->nstate = numstate; (uint state = 0; state < numstate; ++state) { ap->pos[state] = val; val += 0.5; // incrementing testing } } }
}
the actorpos
object defined as:
using actorpos = struct singleactorpositions { unsigned int actor; unsigned int dim; unsigned int nstate; float pos[1000]; // possible upper limit of nstate
};
i'm using ctypes
in python try use function, following code:
import ctypes c actorcnt = 2 dimensioncnt = 2; statecnt = 2 smplib = c.cdll.loadlibrary('libsmpdyn.so') class poshist(c.structure): _fields_ = [("actorid",c.c_uint),\ ("dimensionid",c.c_uint),\ ("statecnt",c.c_uint),\ ('positions',c.c_float*statecnt)] poshistarrtype = poshist*(actorcnt*dimensioncnt) poshists = poshistarrtype() proto_ps = c.cfunctype(c.c_voidp,c.pointer(poshistarrtype),c.c_uint,c.c_uint,c.c_uint) getvphistory = proto_ps(('getvphistory',smplib)) getvphistory(poshists,actorcnt,dimensioncnt,statecnt)
this runs no errors, when try access returned data inside poshists
, see first object has been filled. running this:
for p in poshists: print('actor: %d, dimension: %d'%(p.actorid,p.dimensionid)) o in p.positions: print('\t%0.2f'%o)
gives me this:
actor: 0, dimension: 0 1.00 1.50 actor: 0, dimension: 0 0.00 0.00 actor: 0, dimension: 0 0.00 0.00 actor: 0, dimension: 0 0.00 0.00
i.e., after first poshist
object in array, others still show initial values. can confirm getvphistory
function filling out array, seems me issue of full array not getting passed poshists
variable. please!
edit
suspecting struct part of issue - , more needed problem - i've simplified use 3-d array. c getvphistory
function now:
void getvphistory(float hist[100][100][100], uint numact, uint numdim, uint numstate) { // talk little cout << "actors: " << numact << "dimensions: " << numdim << "states: " << numstate << endl; // loop through actors, dims, , states , store positions float val = 1.0; (uint actor = 0; actor < numact; ++actor) { //cout << "actor " << actor << endl; (uint dim = 0; dim < numdim; ++dim) { //cout << "dimension " << dim << endl; (uint state = 0; state < numstate; ++state) { hist[actor][dim][state] = val; cout << "a: " << actor << " d: " << dim << " s: " << state << "\tadded position: " << val << endl; val += 0.5; } } } }
and python code now:
actorcnt = 3; dimensioncnt = 2; statecnt = 5 poshisttype = ((c.c_float * statecnt) * dimensioncnt)*actorcnt proto_ps = c.cfunctype(c.c_voidp,c.pointer(poshisttype),c.c_uint,c.c_uint,c.c_uint) getvphistory = proto_ps(('getvphistory',smplib)) poshists = poshisttype() getvphistory(poshists,actorcnt,dimensioncnt,statecnt) in range(actorcnt): d in range(dimensioncnt): print('pos hist actor %d, dimension %d:'%(a,d)) print('\t[%s]'%', '.join(['%0.2f'%p p in poshists[a][d]]))
so i'm passing pointer memory 3-d array, data filled in in c, , read data in python. console output c verifies data being stored:
actors: 3 dimensions: 2 states: 5 a: 0 d: 0 s: 0 added position: 1 a: 0 d: 0 s: 1 added position: 1.5 a: 0 d: 0 s: 2 added position: 2 a: 0 d: 0 s: 3 added position: 2.5 ... a: 2 d: 1 s: 2 added position: 14.5 a: 2 d: 1 s: 3 added position: 15 a: 2 d: 1 s: 4 added position: 15.5
yet, without complication of struct, have same issue of first inner-most array coming data:
pos hist actor 0, dimension 0: [1.00, 1.50, 2.00, 2.50, 3.00] pos hist actor 0, dimension 1: [0.00, 0.00, 0.00, 0.00, 0.00] pos hist actor 1, dimension 0: [0.00, 0.00, 0.00, 0.00, 0.00] pos hist actor 1, dimension 1: [0.00, 0.00, 0.00, 0.00, 0.00] pos hist actor 2, dimension 0: [0.00, 0.00, 0.00, 0.00, 0.00] pos hist actor 2, dimension 1: [0.00, 0.00, 0.00, 0.00, 0.00]
if hard code array in c function definition hist[3][2][5]
- same it's created in python - same behavior occurs.
you have declare structure same dimensions betweeen c++ , python:
working (windows) c++ dll:
typedef unsigned int uint; struct actorpos { unsigned int actor; unsigned int dim; unsigned int nstate; float pos[1000]; // possible upper limit of nstate }; extern "c" __declspec(dllexport) void getvphistory(actorpos allpostions[], uint numact, uint numdim, uint numstate) { uint actordimpairindex = 0; float val = 1.0; for(uint actor = 0; actor < numact; ++actor) { for(uint dim = 0; dim < numdim; ++dim) { actorpos* ap = &allpostions[actordimpairindex]; ++actordimpairindex; ap->actor = actor; ap->dim = dim; ap->nstate = numstate; for(uint state = 0; state < numstate; ++state) { ap->pos[state] = val; val += 0.5; // incrementing testing } } } }
python code:
import ctypes c actorcnt = 2; dimensioncnt = 2; statecnt = 2 smplib = c.cdll('test') class poshist(c.structure): _fields_ = [("actorid",c.c_uint),\ ("dimensionid",c.c_uint),\ ("statecnt",c.c_uint),\ ('positions',c.c_float*1000)] # declare same size struct in c++ poshistarrtype = poshist*(actorcnt*dimensioncnt) poshists = poshistarrtype() proto_ps = c.cfunctype(c.c_voidp,c.pointer(poshistarrtype),c.c_uint,c.c_uint,c.c_uint) getvphistory = proto_ps(('getvphistory',smplib)) getvphistory(poshists,actorcnt,dimensioncnt,statecnt) p in poshists: print('actor: %d, dimension: %d'%(p.actorid,p.dimensionid)) # here, iterate number of states returned... in range(p.statecnt): print('\t%0.2f'%p.positions[i])
output:
actor: 0, dimension: 0 1.00 1.50 actor: 0, dimension: 1 2.00 2.50 actor: 1, dimension: 0 3.00 3.50 actor: 1, dimension: 1 4.00 4.50
Comments
Post a Comment