gpt4 book ai didi

python - 从 Python 传递字符串时 PyArg_ParseTuple 的段错误

转载 作者:太空宇宙 更新时间:2023-11-04 02:21:25 27 4
gpt4 key购买 nike

我正在尝试编写一个接受 numpy 数组作为输入的 C 扩展。一切正常,除非我传入一个字符串作为参数。

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "../../include/Python.h"
#include "../../include/arrayobject.h"

static PyObject *max(PyObject *self, PyObject *args)
{
PyArrayObject *arr;
long i, n, strides;

if (PyArg_ParseTuple(args, "O!", &PyArray_Type, &arr)){
/* Get some info about the data. */
n = PyArray_DIMS(arr)[0];
strides = PyArray_STRIDES(arr)[0];
void *data0 = PyArray_DATA(arr);
int typenum = PyArray_TYPE(arr);

if (typenum == NPY_DOUBLE){
double max = *(double *)data0;
for (i=0; i<n; ++i){
if (*(double *)data0 > max){
max = *(double *)data0;
}
data0 += strides;
}
return Py_BuildValue("d", max);
}
else if (typenum == NPY_LONG){
long max = *(long *)data0;
for (i=0; i<n; ++i){
if (*(long *)data0 > max){
max = *(long *)data0;
}
data0 += strides;
}
return Py_BuildValue("l", max);
}
else {
PyErr_Format(
PyExc_TypeError, "\rInput should be a numpy array of numbers."
);
return NULL;
}
}
else{
PyErr_Format(
PyExc_TypeError, "\rInput should be a numpy array of numbers."
);
return NULL;
}
}

static PyMethodDef DiffMethods[] =
{
{"max", max, METH_VARARGS, "Compute the maximum of a numpy array."},
{NULL, NULL, 0, NULL}
};

static struct PyModuleDef cModPyDem =
{PyModuleDef_HEAD_INIT, "_math_functions", "", -1, DiffMethods};

PyMODINIT_FUNC PyInit__math_functions(void)
{
import_array();
return PyModule_Create(&cModPyDem);
}

然后我运行这个 setup.py 脚本:

def configuration(parent_package=None, top_path=None):
import numpy
from numpy.distutils.misc_util import Configuration
config.add_extension('_math_functions', ['_math_functions.c'])

return config

if __name__ == "__main__":
from numpy.distutils.core import setup
setup(configuration=configuration)

使用这些命令:

python setup.py config --compiler=gnu99 build_ext --inplace
rm -rf build/

而且效果很好。该函数在大多数情况下都有效:

In [1]: import _math_functions as mf

In [2]: import numpy as np

In [3]: x = np.random.randint(-1e3, 1e3, size=100)

In [4]: np.max(x), mf.max(x)
Out[4]: (998, 998)

In [5]: x = np.random.rand(100)

In [6]: np.max(x), mf.max(x)
Out[6]: (0.9962604850115798, 0.9962604850115798)

它还可以处理不适当的输入,某种程度上:

In [7]: x = np.array([1,2,"bob"])

In [8]: mf.max(x)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-7ced17af9505> in <module>()
----> 1 mf.max(x)

Input should be a numpy array of numbers.

In [9]: mf.max("bob")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-a656f60cf00d> in <module>()
----> 1 mf.max("bob")

Input should be a numpy array of numbers.

以下输入时出现问题:

In [10]: x = np.array("Bob")

In [11]: mf.max(x)
Segmentation fault: 11

编辑:我尝试过的一些事情。使用:

PyArg_ParseTuple(args, "O", &arr)

相反,这仍然会出现段错误。我还将 printf("i") 放在每一行之前(i=1、2、...),所以我确定段错误发生在 PyArg_ParseTuple 处。

我通读了文档并找到了 "O&" 选项,但无法让它工作。欢迎就如何正确使用它提出任何建议。

我还浏览了这些相关帖子: PyArg_ParseTuple causing segmentation fault

PyArg_ParseTuple SegFaults in CApi(不确定如何解决这个问题...)

Crash when calling PyArg_ParseTuple on a Numpy array

关于如何正确处理这个问题的任何线索?我想要的输出是引发 TypeError。

谢谢!

最佳答案

您是否尝试过添加调试语句来找出代码中发生段错误的确切位置?

假设段错误发生在这里:

if (PyArg_ParseTuple(args, "O!", &PyArray_Type, &arr)) {

尝试添加一个不同的解析机制,如 "O",以便不假设传递了一个 PyArrayObject 实例;然后尝试使用生成的泛型 PyObject* 并检查其类型(参见 PyObject_TypeCheck)并根据类型控制程序的流程。 Extensions 文档中解释了从这里引发异常的方式,但我认为它是这样的:

PyErr_SetString(PyExc_TypeError, "Input should be a numpy array of numbers.");
return NULL;

关于python - 从 Python 传递字符串时 PyArg_ParseTuple 的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57446075/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com