【问题标题】:Numpy, creating 1D array in C++ segfaultsNumpy,在 C++ 段错误中创建一维数组
【发布时间】:2017-03-14 12:32:27
【问题描述】:

我正在尝试在 C++ 中为 numpy 创建一维数组:

PyObject* foo()
{
   npy_intp length[1];
   length[0] = 10;
   PyObject* my_array = PyArray_SimpleNew(1, length, NPY_DOUBLE);
   return boost::python::incref(my_array);
}

然后我做一个python模块:

BOOST_PYTHON_MODULE(pyMod)
{
    using namespace boost::python;

    import_array();

    def("foo", foo);
}

当我在 python 中运行它时,调用 foo(),它在执行对 PyArray_SimpleNew 的调用时会出现段错误,即使我已经调用了 import_array,这似乎是导致这种段错误的常见原因。如果我制作一个维度为 [10, 1] 的二维数组,则效果很好,即:

PyObject* foo()
{
   npy_intp length[2] = {10, 1};
   PyObject* my_array = PyArray_SimpleNew(2, length, NPY_DOUBLE);
   return boost::python::incref(my_array);
}

在python中是这样使用的

import numpy as np
import pyMod

if __name__ == "__main__":
    v = pyMod.foo()

对为什么会出现此段错误有任何想法吗?

【问题讨论】:

  • 在哪一行出现段错误?请提供带有详细错误消息的minimal reproducible example只是一个函数;向我们展示你如何调用它)
  • 调用 PyArray_SimpleNew 时出现段错误
  • 我的评论不仅仅是第一句话。

标签: python c++ numpy boost-python


【解决方案1】:

我不确定您是如何将 PyObject* 暴露给 Python,但我认为正确的方法是通过 boost::python::object 暴露它。

另一点是您正在使用 PyObject 调用 boost::python::object。尽管有可能,但不建议这样做(参见 David Abrahams 撰写的 guidelines)。所以应该使用 boost::python::handle 来解决这种情况。

boost::python::object foo()
{
   npy_intp dims[1] = {10};
   PyObject* p_array = PyArray_SimpleNew(boost::size(dims), dims, NPY_FLOAT);
   boost::python::handle<> handle(boost::python::borrowed(p_array));
   return boost::python::object(handle);
}

【讨论】:

  • 不要认为这是问题所在,因为它在返回之前会崩溃并适用于 2D 数组。不过谢谢你的回答。
  • 仅仅因为它使用二维数组并不意味着它是正确的。我已经编辑了答案,提供了一个解释句柄重要性的链接。
  • 但是我需要一个来自 boost::python::object 的转换器,它只返回 incref(boost_py_obj->ptr()): PyObject* convert(boost::python::object obj) {返回 boost::python::incref(obj->ptr)); }?
  • 我已将问题编辑为不使用 boost::python::object,然后我不需要句柄,因为我没有通过 boost::python::object?
猜你喜欢
  • 2014-10-19
  • 1970-01-01
  • 2023-01-04
  • 1970-01-01
  • 2020-09-10
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
相关资源
最近更新 更多