Python* 至 boost::python::object
Python* to boost::python::object
我正在尝试用 C++ 构建一个 Python 模块,将二维向量转换为 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提供的变量和对象,所以如果你想return一个数组到python应该是个好主意使用 boost::python::dict,类似...
boost::python::dict arr;
int i = 0;
for (auto &item: array) {
arr[i] = item;
++i;
}
return arr;
boost::python::object
provides a generalized interface to Python objects. To construct one from a PyObject*
, one must first construct a boost::python::handle<>
,本质上是一个智能指针,旨在管理引用计数的Python对象(PyObject*
或派生类型)。人们经常在 Boost.Python 的高级代码和 Python/C API.
之间的边界之间使用 handle<>
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 从 PyObject*
构建 boost::python::object
:
#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()
,它只是 returns Python 字符串。重要的是查阅文档以确定 PyObject*
是否被借用,以及对象与其参数之间是否存在任何生命周期要求。在PyArray_SimpleNewFromData()
的情况下,返回的是PyObject*
:
- 它的引用计数已经增加
- 提供给数组的底层内存的生命周期必须至少与返回的
PyObject
一样长。原题中的build_day()
函数不满足这个要求
我正在尝试用 C++ 构建一个 Python 模块,将二维向量转换为 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提供的变量和对象,所以如果你想return一个数组到python应该是个好主意使用 boost::python::dict,类似...
boost::python::dict arr;
int i = 0;
for (auto &item: array) {
arr[i] = item;
++i;
}
return arr;
boost::python::object
provides a generalized interface to Python objects. To construct one from a PyObject*
, one must first construct a boost::python::handle<>
,本质上是一个智能指针,旨在管理引用计数的Python对象(PyObject*
或派生类型)。人们经常在 Boost.Python 的高级代码和 Python/C API.
handle<>
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 从 PyObject*
构建 boost::python::object
:
#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()
,它只是 returns Python 字符串。重要的是查阅文档以确定 PyObject*
是否被借用,以及对象与其参数之间是否存在任何生命周期要求。在PyArray_SimpleNewFromData()
的情况下,返回的是PyObject*
:
- 它的引用计数已经增加
- 提供给数组的底层内存的生命周期必须至少与返回的
PyObject
一样长。原题中的build_day()
函数不满足这个要求