My question is similar "in spirit" to Segmentation fault in PyArray_SimpleNewFromData
I have a C code that looks like this: (original code actually tests if malloc()
returned NULL)
1 #include <Python.h>
2 #include <numpy/arrayobject.h> // (Not sure if right import)
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 double *calculate_dW(npy_intp *dim_w) {
7 int i;
8 double* data = (double*)malloc(sizeof(double) * dim_w[0]);
9
10 /* Inserts some dummy data */
11 for (i = 0; i < dim_w[0]; i++)
12 data[i] = i;
13
14 return data;
15 }
And then a Cython code that wraps it inside a function:
1 import cython
2 import numpy as np
3 cimport numpy as np
4
5 cdef extern double *calculate_dW(np.npy_intp *dim_w)
6
7 def run_calculate_dW(np.ndarray[np.npy_intp, ndim=1, mode="c"] dim_w):
8 print("Will call calculate_dW")
9 cdef double *dW = calculate_dW(&dim_w[0])
10
11 print("Will call PyArray_SimpleNewFromData")
12 ret = np.PyArray_SimpleNewFromData(
13 1,
14 &dim_w[0],
15 np.NPY_FLOAT64,
16 dW)
17 print("Will print")
18 print(ret)
19 print("Will return")
20 return ret
Which I test with
# runTest.py
1 import numpy as np
2 import multiply
3 a = np.array((10,)) # as expected, using `np.array(10)` won't work
4 print a
5 multiply.run_calculate_dW(a)
And get the following output
$ PYTHONPATH=build/lib.linux-x86_64-2.7/ python runTest.py
[10]
Will call calculate_dW
Will call PyArray_SimpleNewFromData
Segmentation fault (core dumped)
(i.e., a SegFault in the call to PyArray_SimpleNewFromData() (if I replace it by, say, ret = 1
, the Segmentation Fault vanishes). When debugging, I tried many things:
- Changing the number of dimensions to 1;
- Increasing the amount of memory allocated by
malloc()
(to guarantee I was not accessing anything I shouldn't); - Changing
np.NPY_FLOAT32
tonp.float32
; - Changing the way I pass the "shape" of the new array.
I believe I am following precisely the documentation, as well as the answer to this other question. I don't seem to get any compiler error or warning.
Still, I do have noticed that all other codes around in the internet are using C (instead of Python) when they call PyArray_SimpleNewFromData. I tried returning a PyObject*
from the C function, but couldn't get it to compile.
Also, I do get some "Using deprecated NumPy API, disable it by #defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" warning; but I have read I am safe to ignore them. (Cython Numpy warning about NPY_NO_DEPRECATED_API when using MemoryView )
Any suggestion? (also, any other way of creating a numpy array out of dW
?)
I think the issue is that you're passing a Python list as the second argument to
PyArray_SimpleNewFromData
when it expects a pointer to an integer. I'm a little surprised this compiles.Try:
Note that I've also changed the type to
NPY_FLOAT64
since that should matchdouble
.I'd also change the definition of
dim_w
toto ensure that the type of the array matches what numpy is expecting. This may also require changing the signature of
calculate_dW
todouble *calculate_dW(intptr_t *dim_w)
to match too.Edit: A second issue is that you need to include the line
in your Cython file (just at the top level, after your imports). This does some setup stuff for numpy. In principle I think the documentation recommends you always include it when doing
cimport numpy
. In practice it only sometimes matter, and this is one of those times.(Answer is now tested)