gpt4 book ai didi

Python* 到 boost::python::object

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:34:06 28 4
gpt4 key购买 nike

我正在尝试用 C++ 构建一个 Python 模块,将二维 vector 转换为 Numpy 二维数组。这里有什么不正确的地方 - 大概需要对 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"));
}

最佳答案

boost::python::object 为 Python 对象提供通用接口(interface)。从 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);

请注意 handle将分享 PyObject* 的所有权,并且在销毁期间,它会减少对 PyObject 的引用计数。它正在管理。因此,在构建期间,重要的是指定是否handle<>需要增加 PyObject* 的引用计数.

如果PyObject已经增加了它的引用计数,然后使用:

namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(py_object);
python::object object(handle);

如果PyObject没有增加它的引用计数,句柄必须这样做,然后使用 borrowed() 施工期间的功能:

namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(python::borrowed(py_object));
python::object object(handle);

这是一个完整的例子demonstrating build 一个boost::python::object来自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"));
}

交互使用:

>>> import example
>>> day = example.build_day(1, 2);
>>> assert(day)

请注意,要创建一个最小的完整示例,上面的示例有一个模拟的 PyArray_SimpleNewFromData()简单地返回 Python 字符串。重要的是查阅文档以确定 PyObject* 是否存在。是否被借用,以及对象与其参数之间是否存在任何生命周期要求。在 PyArray_SimpleNewFromData() 的情况下, 返回的 PyObject* :

  • 已经增加了它的引用计数
  • 提供给数组的底层内存的生命周期必须至少与返回的 PyObject 一样长. build_day()原题中的函数不满足这个要求。

关于Python* 到 boost::python::object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31468724/

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