fredbaba
fredbaba

Reputation: 1496

Amending a Boost Python wrapper class?

How do I access the boost::python::class_ object that's been registered for a given C++ class? I'm importing a boost::python module which defines a wrapper for boost::property_tree::ptree, but I would like to add additional methods to this wrapper definition. When I attempt to create a new wrapper, Boost Python complains that a handler has already been declared, and ignores my new definition.

Any ideas?

Upvotes: 2

Views: 667

Answers (2)

luc
luc

Reputation: 332

I had a similar question, with one difference: As the class export definition was in my own code, I was able to change the part where the boost::python::class_ was first called.

If this is also possible in your case, a solution might look like this:

static auto ptree_class_ = boost::python::class_< ptree > ( "ptree" );

// somewhere later in your code:
ptree_class_.def("contains", &ptree__contains);

This eliminates the need for extra Python code -- all is done in C++.

Here you can find my original solution: https://stackoverflow.com/a/30622038/4184258

Upvotes: 0

fredbaba
fredbaba

Reputation: 1496

Following the suggestion of daramarak, as well as the Boost Python tutorial Extending Wrapped Objects In Python, I extended the class from within python. Python, and thus Boost::Python make little distinction between bound member functions and functions whose first argument is an object reference (or pointer). Thus you can define a function in C++ like so:

bool ptree__contains(boost::property_tree::ptree* self, const std::string& key) {
    return self->find(key)!=self->not_found();
}

And then augment the imported class in Python like so:

from other_module import ptree
from my_module import ptree__contains

# The __contains__ method is a special api function 
# that enables "foo in bar" boolean test statements
ptree.__contains__ = ptree__contains

test_ptree = ptree()
test_ptree.put("follow.the.yellow.brick.road", "OZ!")

print "follow.the.yellow.brick.road" in test_ptree
# > true

I added my augmentation code to the __init__.py of my module, such that any imports of my module would automatically add the desired methods to the external object. I defined a function which modified the class, called this function, and then deleted it to clean up my namespace. Alternatively, you can exclude this function from your __all__ listing to keep it from being exported by from module import * statements. Works like a charm! Thanks again to daramarak.

Upvotes: 3

Related Questions