gpt4 book ai didi

python - 从 C++ 中在本地范围内创建 Python 对象

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

我正在使用 boost.python 使两个 C++ 类可用于 Python,

class X {
public:
X();
}
class Y {
...
}

BOOST_PYTHON_MODULE(test) {
class_<X>("X", init<>());
class_<Y>("Y", init<>());
}

每当我在 Python 中创建一个新的 X 时,我都想在 C++ 中运行一些代码来创建一个类型为 Y 的本地对象“y”。如此有效,当我这样做时

x = X()

在 Python 中,我希望它运行

y = Y()

同样,但是来自 C++ 中的 X::X() 构造函数。

我想用类似的东西

scope().attr("y")=...

在 X::X() 构造函数中,但是当以这种方式调用时,作用域总是返回一个 NoneType 对象(如果我在 BOOST_PYTHON_MODULE 中使用这个构造,它工作正常,但那不适合我)。

最佳答案

boost::python::scope更类似于命名空间而不是代码块的范围。 Python/C API 公开了一个类似于 locals() 的字典。通过PyEval_GetLocals()功能。可以使用这个字典将变量注入(inject)当前作用域。

// Borrow a reference from the locals dictionary to create a handle.
// If PyEval_GetLocals() returns NULL, then Boost.Python will throw.
namespace python = boost::python;
python::object locals(python::borrowed(PyEval_GetLocals()));

// Inject an instance of Y into the frame's locals as variable 'y'.
// Boost.Python will handle the conversion of C++ Y to Python Y.
locals["y"] = Y();

这是一个完整的例子,当 example.X 被调用时,example.Y 的一个实例作为变量 y 被注入(inject)到调用者的作用域中构造。

#include <boost/python.hpp>

/// @brief Mockup types.
struct X {};
struct Y {};

/// @brief Auxiliary function that will create X and inject an Y object
/// as 'y' into the caller's frame.
X* make_x_and_inject_y()
{
// Boost.Python objects may throw, so use a smart pointer that can
// release ownership to manage memory.
std::auto_ptr<X> x(new X());

// Borrow a reference from the locals dictionary to create a handle.
// If PyEval_GetLocals() returns NULL, then Boost.Python will throw.
namespace python = boost::python;
python::object locals(python::borrowed(PyEval_GetLocals()));

// Inject an instance of Y into the frame's locals as variable 'y'.
// Boost.Python will handle the conversion of C++ Y to Python Y.
locals["y"] = Y();

// Transfer ownership of X to Boost.Python.
return x.release();
}

BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;

// Expose X, explicitly suppressing Boost.Python from creating a
// default constructor, and instead exposing a custom constructor.
python::class_<X>("X", python::no_init)
.def("__init__", python::make_constructor(&make_x_and_inject_y))
;
python::class_<Y>("Y", python::init<>());
}

交互使用:

>>> import example
>>> def fun():
... assert('y' not in dir())
... example.X()
... assert('y' in dir()) # creating X injects y into scope
...
>>> assert('y' not in dir())
>>> fun()
>>> assert('y' not in dir())
>>> example.X()
<example.X object at 0xb746fa7c>
>>> assert('y' in dir()) # creating X injects y into scope
>>> assert(isinstance(y, example.Y))

在这个实现中,我选择向 Python 公开一个辅助工厂函数作为 X 的构造函数,而不是让 X 的 C++ 构造函数执行注入(inject) Y。这只是个人偏好,但我经常发现它通过限制可识别 Python 的 C++ 类型的数量来提供语言之间更清晰的界限。

关于python - 从 C++ 中在本地范围内创建 Python 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22276502/

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