Python*来boost :: python :: object

tim*_*mbo 6 c++ python boost numpy boost-python

我试图用C++构建一个Python模块,将2D矢量转换为Numpy 2D数组.这里有什么不对的 - 可能是PyObject*中的boost python对象需要进行一些转换?

boost::python::object build_day(int year, int day) {

  PyObject* arr;
  const int HEIGHT = 5;
  const int WIDTH = 5;

  std::vector<std::vector<float> > array(WIDTH, std::vector<float>(HEIGHT));

  npy_intp dims[2] = {WIDTH, HEIGHT};
  arr = PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, &array);

  return arr; 
}

BOOST_PYTHON_MODULE(sumpar) {
  using namespace boost::python;
  def("build_day", build_day, args("year", "day"));
}
Run Code Online (Sandbox Code Playgroud)

Tan*_*ury 5

boost::python::object提供了一个通用接口,Python对象。要从构造一个PyObject*,必须首先构造一个boost::python::handle<>,它本质上是一个智能指针,旨在管理引用计数的Python对象(PyObject*或派生类型)。通常handle<>在Boost.Python的高级代码与Python / C API之间的边界之间使用。

namespace python = boost::python;
PyObject* py_object = get_py_object();
python::handle<> handle(py_object);
boost::python object(handle);
Run Code Online (Sandbox Code Playgroud)

请注意,handle将共享的所有权PyObject*,并且在销毁期间,它将减少所PyObject管理的引用计数。因此,在施工过程中,重要的是指定是否handle<>需要增加的参考计数PyObject*

如果PyObject已经增加了其引用计数,则使用:

namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(py_object);
python::object object(handle);
Run Code Online (Sandbox Code Playgroud)

如果PyObject尚未增加其引用计数,而句柄必须这样做,则borrowed()在构造过程中使用该函数:

namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(python::borrowed(py_object));
python::object object(handle);
Run Code Online (Sandbox Code Playgroud)

这是一个完整的示例,展示了如何boost::python::object从中构造a PyObject*

#include <vector>
#include <boost/python.hpp>

// Mocks...
enum { NPY_FLOAT };
typedef int npy_intp;
PyObject* PyArray_SimpleNewFromData(int, npy_intp*, int, void*)
{
  return PyString_FromString("hello world");
}

boost::python::object build_day(int year, int day)
{
  const int HEIGHT = 5;
  const int WIDTH = 5;

  std::vector<std::vector<float> > array(
      WIDTH, std::vector<float>(HEIGHT));

  npy_intp dims[2] = {WIDTH, HEIGHT};

  namespace python = boost::python;
  PyObject* arr = PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, &array);
  python::handle<> handle(arr);
  return python::object(handle);
}

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::def("build_day", &build_day, python::args("year", "day"));
}
Run Code Online (Sandbox Code Playgroud)

互动用法:

>>> import example
>>> day = example.build_day(1, 2);
>>> assert(day)
Run Code Online (Sandbox Code Playgroud)

请注意,为了创建一个最小的完整示例,上面的示例具有一个PyArray_SimpleNewFromData()仅返回Python字符串的模型。重要的是,请查阅文档以确定是否PyObject*借用了对象,以及对象及其参数之间是否存在生存期要求。如果是PyArray_SimpleNewFromData(),则返回PyObject*

  • 已经增加了参考数量
  • 提供给数组的基础内存的生存期必须至少与返回的生存期一样长PyObjectbuild_day()原始问题中的功能无法满足此要求。