Reputation: 11
I'm trying to build up a python C extension in order to pass a numpy matrix to a C array. I was following the suggestions reported here:
http://wiki.scipy.org/Cookbook/C_Extensions/NumPy_arrays
but when Python tries to run the C line:
v=(float **)malloc((size_t) (n*sizeof(float)));
of the follow portion of code:
float **_ptrvector(long n) {
float **v;
v=(float **)malloc((size_t) (n*sizeof(float)));
if (!v) {
printf("In **ptrvector. Allocation of memory for array failed.");
exit(0); }
return v;
}
float **pymatrix_to_carray(PyArrayObject *arrayin) {
float **c, *a;
int i,n,m;
n = PyArray_DIM(arrayin, 0);
m = PyArray_DIM(arrayin, 1);
c=_ptrvector(n);
a = (float*) PyArray_DATA(arrayin);
for ( i=0; i<n; i++) {
c[i]=a+i*m; }
return c;
}
I get a segmentation fault on my Linux 64 bit machine. The problem is that this code works perfectly on 32 bit machines (both Windows and Linux). Moreover sizeof(size_t) returns correctly 4 on 32bit machines and 8 on 64bit machines. I'm using Python 2.7.1 [EPD 7.0-2 (64-bit)] and GCC 4.1.2 on a Red Hat Linux 4.2.1-44 with kernel version 2.6.18.
I tried also with npy_intp and also Py_ssize_t instead of size_t but no positive effect.
Upvotes: 1
Views: 433
Reputation: 70941
Here you want to allocate memory for pointers to float
:
float **v;
v=(float **)malloc((size_t) (n*sizeof(float)));
but you do allocated memory for float
s themselfes. On a 32bit system pointers need 4 bytes, so this works.
On a 64bit system pointers need 8 byte, so you might like to change the above line to be:
float ** v = malloc(n * sizeof(float*));
or even more secure to
float ** v = malloc(n * sizeof(*v));
Btw: In C it is not needed to caste the result of malloc/calloc/realloc
nor is it recommended. Even more it is dangerous to do so as it might hide awful mistakes.
Upvotes: 2