如何在 boost::python 中向模块添加属性?

发布于 2024-08-30 21:36:52 字数 541 浏览 7 评论 0原文

您可以使用 getter 和 setter (在简单的情况下)向类添加属性:

class<X>("X")
    .add_property("foo", &X::get_foo, &X::set_foo);

那么您可以像这样从 python 中使用它:

>>> x = mymodule.X()
>>> x.foo = 'aaa'
>>> x.foo
'aaa'

但是如何向模块本身(而不是类)添加属性?

使用上述两种方式添加类

scope().attr("globalAttr") = ??? something ???

我可以

def("globalAttr", ??? something ???);

的全局函数和对象,但似乎无法像在类中那样添加属性。

You can add a property to a class using a getter and a setter (in a simplistic case):

class<X>("X")
    .add_property("foo", &X::get_foo, &X::set_foo);

So then you can use it from python like this:

>>> x = mymodule.X()
>>> x.foo = 'aaa'
>>> x.foo
'aaa'

But how to add a property to a module itself (not a class)?

There is

scope().attr("globalAttr") = ??? something ???

and

def("globalAttr", ??? something ???);

I can add global functions and objects of my class using the above two ways, but can't seem to add properties the same way as in classes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苍暮颜 2024-09-06 21:36:53

__getattr____setattr__ 不会在模块上调用,因此您

__getattr__ and __setattr__ aren't called on modules, so you can't do this in ordinary Python without hacks (like storing a class in the module dictionary). Given that, it's very unlikely there's an elegant way to do it in Boost Python either.

痴意少年 2024-09-06 21:36:53

Python Wiki 上的 boost.python/HowTo有一个将 C++ 对象公开为 BOOST_PYTHON_MODULE 内的模块属性的示例:

namespace bp = boost::python;
BOOST_PYTHON_MODULE(example)
{
    bp::scope().attr("my_attr") = bp::object(bp::ptr(&my_cpp_object));
}

要在 BOOST_PYTHON_MODULE 之外设置属性,请使用

bp::import("example").attr("my_attr") = bp::object(bp::ptr(&my_cpp_object));

现在您可以在 python 中执行类似的操作

from example import my_attr

当然,您需要提前注册 my_cpp_object 类(例如,您可以在同一个 BOOST_PYTHON_MODULE 调用中执行此操作)并确保 C++ 对象生命周期超过 python 模块的生命周期。您可以使用任何 bp::object 而不是包装 C++ 对象。

请注意,BOOST_PYTHON_MODULE 会吞掉异常,因此,如果您犯了错误,您不会收到任何错误指示,并且 BOOST_PYTHON_MODULE 生成的函数将立即返回。为了简化这种情况的调试,您可以捕获 BOOST_PYTHON_MODULE 内部的异常,或者临时添加一些日志语句作为 BOOST_PYTHON_MODULE 的最后一行,以查看是否已达到:

BOOST_PYTHON_MODULE(example)
{
    bp::scope().attr("my_attr2") = new int(1); // this will compile
    std::cout << "init finished\n"; // OOPS, this line will not be reached
}

boost.python/HowTo on Python Wiki has an example of exposing C++ object as a module attribute inside BOOST_PYTHON_MODULE:

namespace bp = boost::python;
BOOST_PYTHON_MODULE(example)
{
    bp::scope().attr("my_attr") = bp::object(bp::ptr(&my_cpp_object));
}

To set the attribute outside of BOOST_PYTHON_MODULE use

bp::import("example").attr("my_attr") = bp::object(bp::ptr(&my_cpp_object));

Now you can do in python something like

from example import my_attr

Of course, you need to register class of my_cpp_object in advance (e.g. you can do this inside the same BOOST_PYTHON_MODULE call) and ensure C++ object lifetime exceeds that of the python module. You can use any bp::object instead of wrapping C++ one.

Note that BOOST_PYTHON_MODULE swallows exceptions, so if you make a mistake, you don't receive any error indication and BOOST_PYTHON_MODULE-generated function will just immediately return. To ease debugging of this case you can catch exceptions inside BOOST_PYTHON_MODULE or temporary add some logging statement as a last line of BOOST_PYTHON_MODULE to see that it is reached:

BOOST_PYTHON_MODULE(example)
{
    bp::scope().attr("my_attr2") = new int(1); // this will compile
    std::cout << "init finished\n"; // OOPS, this line will not be reached
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文