12

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.

Alex B
  • 82,554
  • 44
  • 203
  • 280

2 Answers2

3

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
}
Ilia K.
  • 4,822
  • 2
  • 22
  • 19
3

__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.

Community
  • 1
  • 1
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539