在Numpy数组上调用PyArg_ParseTuple时崩溃

时间:2016-06-21 11:52:59

标签: python c arrays numpy

我在C中编写了一个简单的Python扩展函数,只读取Numpy数组并崩溃。

static PyObject *test(PyObject *self, PyObject *args)
{
    PyArrayObject *array = NULL;

    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &array)) // Crash
        return NULL;

    return Py_BuildValue("d", 0);
}

以下是它的调用方式:

l = np.array([1,2,3,1,2,2,1,3])

print("%d" % extension.test(l))

我的代码出了什么问题?

2 个答案:

答案 0 :(得分:4)

我认为错误出现在您未在示例中包含的代码中:您是否记得在模块初始化函数中调用import_array()

  

...此子例程还必须包含对import_array()和/或import_ufunc()的调用,具体取决于所需的C-API。只要实际调用任何C-API子例程,忘记放置这些命令就会显示为一个丑陋的分段错误(崩溃)。

http://docs.scipy.org/doc/numpy-1.10.1/user/c-info.how-to-extend.html#required-subroutine

我逐字复制你的例子并添加(使用python 3)

PyMODINIT_FUNC
PyInit_numpytest(void)
{
    import_array();
    return PyModule_Create(&numpytest);
}

并且示例运行没有问题。另一方面,删除呼叫会导致崩溃。

答案 1 :(得分:0)

MacOS 和 Linux 的区别

以下在 Linux 上对我来说很好用:

PyMODINIT_FUNC PyInit_numpytest(void) {
    import_array();
    return PyModule_Create(&numpytest);
}

但是,在使用 MacOS 时,尝试导入库时出现以下错误:

SystemError: лy () method: bad call flags

以下适用于 MacOS 和 Linux:

PyMODINIT_FUNC PyInit_numpytest(void) {
    PyObject* mod = PyModule_Create(&numpytest);
    import_array();
    return mod;
}

请注意,我所做的只是更改了 PyModule_Createimport_array 的顺序。