我的问题与PyArray_SimpleNewFromData中的细分错误在精神上类似
我有一个看起来像这样的C代码:(原始代码实际上测试是否malloc()
返回NULL)
1 #include2 #include // (Not sure if right import) 3 #include 4 #include 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 }
然后是将其包装在函数中的Cython代码:
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
我测试
# 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)
并得到以下输出
$ PYTHONPATH=build/lib.linux-x86_64-2.7/ python runTest.py [10] Will call calculate_dW Will call PyArray_SimpleNewFromData Segmentation fault (core dumped)
(即,对PyArray_SimpleNewFromData()的调用中出现了SegFault(如果我将其替换ret = 1
为Segmentation Fault消失了)。在调试时,我尝试了很多事情:
将尺寸数更改为1;
增加分配的内存量malloc()
(以确保我没有访问我不应该访问的任何内容);
更改np.NPY_FLOAT32
到np.float32
;
改变我传递新数组“形状”的方式。
我相信我会严格遵循文档说明以及对其他问题的解答。我似乎没有收到任何编译器错误或警告。
不过,我确实注意到,互联网上所有其他代码在调用PyArray_SimpleNewFromData时都在使用C(而不是Python)。我尝试PyObject*
从C函数返回a ,但无法对其进行编译。
另外,我确实得到一些“使用不推荐使用的NumPy API,通过#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION禁用它”警告;但我读过,我可以放心地忽略它们。(使用MemoryView时,有关NPY_NO_DEPRECATED_API的Cython Numpy警告)
有什么建议吗?(此外,还可以使用其他任何方法来创建numpy数组dW
吗?)
我认为问题在于,您正在传递Python列表作为第二个参数,PyArray_SimpleNewFromData
即它期望指向整数的指针。我对此编译感到有些惊讶。
尝试:
ret = np.PyArray_SimpleNewFromData( 4, &dim_w[0], # pointer to first element np.NPY_FLOAT64, dW)
请注意,我也将类型更改为,NPY_FLOAT64
因为它应该匹配double
。
我也会将的定义更改dim_w
为
np.ndarray[np.NPY_INTP, ndim=1, mode="c"] dim_w
确保数组的类型与numpy期望的匹配。这可能还需要改变的签名calculate_dW
来double *calculate_dW(intptr_t *dim_w)
搭配了。
编辑:第二个问题是您需要包括该行
np.import_array()
在您的Cython文件中(在导入后位于顶层)。这会为numpy做一些设置。原则上,我认为文档建议您在执行操作时始终将其包括在内cimport numpy
。在实践中,这仅在某些时候很重要,而这就是其中之一。
(现在已测试答案)