Question

I'm trying to send an array of objects to my c library.

The object I'm trying to send is a pymunk Body.It has a pointer object embedded in it Body._body. I was able to pass a single one to my function and extract with Chipmunk functions anything I wanted. I used cpBodyGetMass just as a test and that worked.

If I make an array of these. The only one that works is the first one.

I want to be able to send the Body._body addresses as an array to my dll. I figured I could store the pointer in a c_int or c_long array and convert those addresses to the cpBody that Chipmunk wants.

Here is my Custom function

int pymunk_body(int color_id, int numof, float * values, cpBody * body){

    glBindTexture(GL_TEXTURE_2D,0);
    cpBody bd;
    float red;
    float green;
    float blue;
    float alpha;
    float sizex;
    float sizey;
    cpVect position;
    float positionx;
    float positiony;
    float rotation;

    for (int i=0;i<numof*6;i=i+6){
        bd=body[i/6];
        red=values[0+i];
        green=values[1+i];
        blue=values[2+i];
        alpha=values[3+i];
        sizex=values[4+i];
        sizey=values[5+i];
        position=cpBodyGetPos(body);
        positionx=position.x;
        positiony=position.y;
        rotation=cpBodyGetAngle(body)*180/PI;
    }

My C++ has no python wrapping so I can only send C objects. The way I've been doing this is...

    gldll[4](ctypes.c_int(add_color),
    ctypes.c_float(color[0]),
    ctypes.c_float(color[1]),
    ctypes.c_float(color[2]),
    ctypes.c_float(color[3]),
    ctypes.c_float(position[0]),
    ctypes.c_float(position[1]),
    ctypes.c_float(rotation),
    ctypes.c_float(size[0]),
    ctypes.c_float(size[1]))

and

    ni=numpy.array([self.texture.TextureID,ublur,add_color,blurSize,self.Blur+blur,textfont],"i")
    nf=numpy.array([(self.width+self.height)/2.0,color[0],color[1],color[2],color[3],position[0],position[1],rotation,self.half_width,self.half_height,scale],"f")

    gldll[2](ctypes.c_void_p(ni.ctypes.data),ctypes.c_void_p(nf.ctypes.data))

Now if I send an array of pointers. Basically an array of 4 byte ints. The cpBody body[] assumes that it must jump, in bytes the sizeof(cpBody) in the array to get to the next object. But their not inline. Its a list of random pointers to all the bodies. I need it to read the address in each array element and have it assume that there is a cpBody at that location.

If you look at the second example. I've sent an array via a single pointer. I need to send a pointer to an array of pointers and get the cpBody from each. Which means I need the array to jump only 4 bytes and read the memory address as a cpBody.

Was it helpful?

Solution

This is a short example on one way to send an array of pymunk.Body objects to a c lib:

First the c code:

#include "chipmunk.h"

double mass_sum(size_t numof, cpBody ** body);
double mass_sum(size_t numof, cpBody ** body){
    double total = 0;  
    for (int i=0; i<numof; i++){    
         total += cpBodyGetMass(body[i]);
    }
    return total;
}

Then the python code:

from ctypes import *
import sys
sys.path.insert(0,'..')

import pymunk 

sendbody_lib = windll.LoadLibrary("sendbody.dll")

cpBody = pymunk._chipmunk.cpBody

mass_sum = sendbody_lib.mass_sum
mass_sum.restype = c_double
mass_sum.argtypes = [c_int, POINTER(POINTER(cpBody))]

b1 = pymunk.Body(1, 1)
b2 = pymunk.Body(10, 1)
bodies = [b1._body, b2._body, b1._body]
arr = (POINTER(cpBody) * len(bodies))(*bodies)

print mass_sum(len(arr), arr)  

(I had to modify the path to have my code find pymunk as you can see in the start, but that is only because I dont have it installed into python path by default)

OTHER TIPS

I am not sure but you use cpBodyGetAngle(body) shouldn't it be cpBodyGetAngle(bd) (same for cpBodyGetPos), since that will always decay the array to a pointer to the first element.

If this is not what you are looking for, could you describe what is not working? Does your program crash, yield unexpected results, ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top