Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. — Herb Sutter and Andrei Alexandrescu , C++ Coding Standards

Prev

Exposing Classes

Now let's expose a C++ class to Python.

Consider a C++ class/struct that we want to expose to Python:

We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:

Here, we wrote a C++ class wrapper that exposes the member functions greet and set . Now, after building our module as a shared library, we may use our class World in Python. Here's a sample Python session:

Constructors

Our previous example didn't have any explicit constructors. Since World is declared as a plain struct, it has an implicit default constructor. Boost.Python exposes the default constructor by default, which is why we were able to write

We may wish to wrap a class with a non-default constructor. Let us build on our previous example:

This time World has no default constructor; our previous wrapping code would fail to compile when the library tried to expose it. We have to tell class_<World> about the constructor we want to expose instead.

init<std::string>() exposes the constructor taking in a std::string (in Python, constructors are spelled " "__init__" ").

We can expose additional constructors by passing more init<...> s to the def() member function. Say for example we have another World constructor taking in two doubles:

On the other hand, if we do not wish to expose any constructors at all, we may use no_init instead:

This actually adds an __init__ method which always raises a Python RuntimeError exception.

Class Data Members

Data members may also be exposed to Python so that they can be accessed as attributes of the corresponding Python class. Each data member that we wish to be exposed may be regarded as read-only or read-write . Consider this class Var :

Our C++ Var class and its data members can be exposed to Python:

Then, in Python, assuming we have placed our Var class inside the namespace hello as we did before:

Note that name is exposed as read-only while value is exposed as read-write .

Class Properties

In C++, classes with public data members are usually frowned upon. Well designed classes that take advantage of encapsulation hide the class' data members. The only way to access the class' data is through access (getter/setter) functions. Access functions expose class properties. Here's an example:

However, in Python attribute access is fine; it doesn't neccessarily break encapsulation to let users handle attributes directly, because the attributes can just be a different syntax for a method call. Wrapping our Num class using Boost.Python:

And at last, in Python:

Take note that the class property rovalue is exposed as read-only since the rovalue setter member function is not passed in:

Inheritance

In the previous examples, we dealt with classes that are not polymorphic. This is not often the case. Much of the time, we will be wrapping polymorphic classes and class hierarchies related by inheritance. We will often have to write Boost.Python wrappers for classes that are derived from abstract base classes.

Consider this trivial inheritance structure:

And a set of C++ functions operating on Base and Derived object instances:

We've seen how we can wrap the base class Base :

Now we can inform Boost.Python of the inheritance relationship between Derived and its base class Base . Thus:

Doing so, we get some things for free:

Now, we will expose the C++ free functions b and d and factory :

Note that free function factory is being used to generate new instances of class Derived . In such cases, we use return_value_policy<manage_new_object> to instruct Python to adopt the pointer to Base and hold the instance in a new Python Base object until the the Python object is destroyed. We will see more of Boost.Python call policies later.

Class Virtual Functions

In this section, we will learn how to make functions behave polymorphically through virtual functions. Continuing our example, let us add a virtual function to our Base class:

One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. It is not ideal to add anything to our class Base . Yet, when you have a virtual function that's going to be overridden in Python and called polymorphically from C++ , we'll need to add some scaffoldings to make things work properly. What we'll do is write a class wrapper that derives from Base that will unintrusively hook into the virtual functions so that a Python override may be called:

Notice too that in addition to inheriting from Base , we also multiply- inherited wrapper < Base > (See Wrapper ). The wrapper template makes the job of wrapping classes that are meant to overridden in Python, easier.

add_property boost python

If you are using Microsoft Visual C++ 6 or 7, you have to write f as:

return call < int >( this -> get_override ( "f" ). ptr ()); .

BaseWrap's overridden virtual member function f in effect calls the corresponding method of the Python object through get_override .

Finally, exposing Base :

pure_virtual signals Boost.Python that the function f is a pure virtual function.

Virtual Functions with Default Implementations

We've seen in the previous section how classes with pure virtual functions are wrapped using Boost.Python's class wrapper facilities. If we wish to wrap non -pure-virtual functions instead, the mechanism is a bit different.

Recall that in the previous section , we wrapped a class with a pure virtual function that we then implemented in C++, or Python classes derived from it. Our base class:

had a pure virtual function f . If, however, its member function f was not declared as pure virtual:

We wrap it this way:

Notice how we implemented BaseWrap :: f . Now, we have to check if there is an override for f . If none, then we call Base :: f () .

If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line with the * note * as:

return call < char const *>( f . ptr ()); .

Finally, exposing:

Take note that we expose both & Base :: f and & BaseWrap :: default_f . Boost.Python needs to keep track of 1) the dispatch function f and 2) the forwarding function to its default implementation default_f . There's a special def function for this purpose.

In Python, the results would be as expected:

Calling base.f() :

Calling derived.f() :

Class Operators/Special Functions

Python operators.

C is well known for the abundance of operators. C++ extends this to the extremes by allowing operator overloading. Boost.Python takes advantage of this and makes it easy to wrap C++ operator-powered classes.

Consider a file position class FilePos and a set of operators that take on FilePos instances:

The class and the various operators can be mapped to Python rather easily and intuitively:

The code snippet above is very clear and needs almost no explanation at all. It is virtually the same as the operators' signatures. Just take note that self refers to FilePos object. Also, not every class T that you might need to interact with in an operator expression is (cheaply) default-constructible. You can use other<T>() in place of an actual T instance when writing "self expressions".

Special Methods

Python has a few more Special Methods . Boost.Python supports all of the standard special method names supported by real Python class instances. A similar set of intuitive interfaces can also be used to wrap C++ functions that correspond to these Python special functions . Example:

Need we say more?

Prev

Exposing Classes

Now let's expose a C++ class to Python.

Consider a C++ class/struct that we want to expose to Python:

We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:

Here, we wrote a C++ class wrapper that exposes the member functions greet and set . Now, after building our module as a shared library, we may use our class World in Python. Here's a sample Python session:

Constructors

Our previous example didn't have any explicit constructors. Since World is declared as a plain struct, it has an implicit default constructor. Boost.Python exposes the default constructor by default, which is why we were able to write

We may wish to wrap a class with a non-default constructor. Let us build on our previous example:

This time World has no default constructor; our previous wrapping code would fail to compile when the library tried to expose it. We have to tell class_<World> about the constructor we want to expose instead.

init<std::string>() exposes the constructor taking in a std::string (in Python, constructors are spelled " " _init _" ").

We can expose additional constructors by passing more init<...> s to the def() member function. Say for example we have another World constructor taking in two doubles:

On the other hand, if we do not wish to expose any constructors at all, we may use no_init instead:

This actually adds an _init _ method which always raises a Python RuntimeError exception.

Class Data Members

Data members may also be exposed to Python so that they can be accessed as attributes of the corresponding Python class. Each data member that we wish to be exposed may be regarded as read-only or read-write . Consider this class Var :

Our C++ Var class and its data members can be exposed to Python:

Then, in Python, assuming we have placed our Var class inside the namespace hello as we did before:

Note that name is exposed as read-only while value is exposed as read-write .

Class Properties

In C++, classes with public data members are usually frowned upon. Well designed classes that take advantage of encapsulation hide the class' data members. The only way to access the class' data is through access (getter/setter) functions. Access functions expose class properties. Here's an example:

However, in Python attribute access is fine; it doesn't neccessarily break encapsulation to let users handle attributes directly, because the attributes can just be a different syntax for a method call. Wrapping our Num class using Boost.Python:

And at last, in Python:

Take note that the class property rovalue is exposed as read-only since the rovalue setter member function is not passed in:

Inheritance

In the previous examples, we dealt with classes that are not polymorphic. This is not often the case. Much of the time, we will be wrapping polymorphic classes and class hierarchies related by inheritance. We will often have to write Boost.Python wrappers for classes that are derived from abstract base classes.

Consider this trivial inheritance structure:

And a set of C++ functions operating on Base and Derived object instances:

We've seen how we can wrap the base class Base :

Now we can inform Boost.Python of the inheritance relationship between Derived and its base class Base . Thus:

Doing so, we get some things for free:

Now, we shall expose the C++ free functions b and d and factory :

Note that free function factory is being used to generate new instances of class Derived . In such cases, we use return_value_policy<manage_new_object> to instruct Python to adopt the pointer to Base and hold the instance in a new Python Base object until the the Python object is destroyed. We shall see more of Boost.Python call policies later.

Class Virtual Functions

In this section, we shall learn how to make functions behave polymorphically through virtual functions. Continuing our example, let us add a virtual function to our Base class:

One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. It is not ideal to add anything to our class Base . Yet, when you have a virtual function that's going to be overridden in Python and called polymorphically from C++ , we'll need to add some scaffoldings to make things work properly. What we'll do is write a class wrapper that derives from Base that will unintrusively hook into the virtual functions so that a Python override may be called:

Notice too that in addition to inheriting from Base , we also multiply- inherited wrapper < Base > (See Wrapper ). The wrapper template makes the job of wrapping classes that are meant to overridden in Python, easier.

BaseWrap's overridden virtual member function f in effect calls the corresponding method of the Python object through get_override .

Finally, exposing Base :

pure_virtual signals Boost.Python that the function f is a pure virtual function.

Virtual Functions with Default Implementations

We've seen in the previous section how classes with pure virtual functions are wrapped using Boost.Python's class wrapper facilities. If we wish to wrap non -pure-virtual functions instead, the mechanism is a bit different.

Recall that in the previous section , we wrapped a class with a pure virtual function that we then implemented in C++, or Python classes derived from it. Our base class:

had a pure virtual function f . If, however, its member function f was not declared as pure virtual:

We wrap it this way:

Notice how we implemented BaseWrap :: f . Now, we have to check if there is an override for f . If none, then we call Base :: f () .

Finally, exposing:

Take note that we expose both & Base :: f and & BaseWrap :: default_f . Boost.Python needs to keep track of 1) the dispatch function f and 2) the forwarding function to its default implementation default_f . There's a special def function for this purpose.

In Python, the results would be as expected:

Calling base.f() :

Calling derived.f() :

Class Operators/Special Functions

Python operators.

C is well known for the abundance of operators. C++ extends this to the extremes by allowing operator overloading. Boost.Python takes advantage of this and makes it easy to wrap C++ operator-powered classes.

Consider a file position class FilePos and a set of operators that take on FilePos instances:

The class and the various operators can be mapped to Python rather easily and intuitively:

The code snippet above is very clear and needs almost no explanation at all. It is virtually the same as the operators' signatures. Just take note that self refers to FilePos object. Also, not every class T that you might need to interact with in an operator expression is (cheaply) default-constructible. You can use other<T>() in place of an actual T instance when writing "self expressions".

Special Methods

Python has a few more Special Methods . Boost.Python supports all of the standard special method names supported by real Python class instances. A similar set of intuitive interfaces can also be used to wrap C++ functions that correspond to these Python special functions . Example:

Need we say more?

How to expose...

Static class data members, static class functions, at module creation time, at run-time, mutable c++ object, std::c++ container, method 1 (old way), method 2 (new way), method 1 (official), getter and setter methods as a property, named constructors / factories (as python initializers), boost.function objects, a package within a single extension module, c++ object from python, swig exposed c++ object from python, multithreading support for my function, ownership of c++ object, ownership of c++ object extended in python, python object from derived c++ object, python object from extended c++ object, access to a python extension in the same app that embeds python, dynamic template to-python converters., [note] problems using ms visual c++ debugger, module level objects, "raw" function, "raw" constructor, how to get..., how to make..., howto debug your extensions...

boost.python/HowTo (last edited 2015-04-21 17:00:36 by HansDembinski )

Unable to edit the page? See the FrontPage for instructions.

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Strange behavior of add_property in Boost.Python

I met a strange behavior when using add_property of Boost.Python.

Here is the example codes, it simply add two properties (read-only & read-write) to the wrapped class.

and the build command:

I'm working in Cygwin x86_64, so the file extension is .dll . As for Ubuntu just change the output extension to .so .

When importing the bp module, it crashes with a Segmentation fault . The core dump file doesn't contain any call stack information.

However, if I change the order of add_property (as below) to add the read-write property first, it works ok.

My environment:

BTW, there's no problem in Ubuntu 14.04 (64-bit) whatever the add_property order is.

Why would this happen?

nn0p's user avatar

Know someone who can answer? Share a link to this question via email , Twitter , or Facebook .

Your answer, sign up or log in, post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service , privacy policy and cookie policy

Browse other questions tagged c++ boost cygwin boost-python or ask your own question .

Hot Network Questions

add_property boost python

Your privacy

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .

Prev

Chapter 2. High Level Components

Table of Contents

boost/python/class.hpp

Introduction.

< boost / python / class . hpp > defines the interface through which users expose their C++ classes to Python. It declares the class_ class template, which is parameterized on the class type being exposed. It also exposes the init , optional and bases utility class templates, which are used in conjunction with class_ .

< boost / python / class_fwd . hpp > contains a forward declaration of the class_ class template.

Class template class_ < T , Bases , HeldType , NonCopyable >

Creates a Python class associated with the C++ type passed as its first parameter. Although it has four template parameters, only the first one is required. The three optional arguments can actually be supplied in any order ; Boost.Python determines the role of the argument from its type.

HeldType Semantics

Class template class_ synopsis

Class template class_ constructors.

name is an ntbs which conforms to Python's identifier naming rules . If docstring is supplied, it must be an ntbs . If init_spec is supplied, it must be either the special enumeration constant no_init or an init-expression compatible with T .

Constructs a class_ object holding a Boost.Python extension class named name. The named attribute of the current scope is bound to the new extension class.

Allowing the user to specify constructor arguments in the class_ <> constructor helps her to avoid the common run-time errors which result from invoking wrapped member functions without having exposed an __init__ function which creates the requisite T instance. Types which are not default-constructible will cause a compile-time error unless Init is supplied. The user must always supply name as there is currently no portable method to derive the text of the class name from its type.

Class template class_ modifier functions

init_expr is the result of an init-expression compatible with T .

For each valid prefix P of Init , adds an __init__ (...) function overload to the extension class accepting P as arguments. Each overload generated constructs an object of HeldType according to the semantics described above, using a copy of init_expr's call policies. If the longest valid prefix of Init contains N types and init_expr holds M keywords, an initial sequence of the keywords are used for all but the first N - M arguments of each overload.

Allows users to easily expose a class' constructor to Python.

name is an ntbs which conforms to Python's identifier naming rules . * If a1 is the result of an overload-dispatch-expression , only the second form is allowed and fn must be a pointer to function or pointer to member function whose arity is the same as A1's maximum arity .

Effects: For each prefix P of Fn 's sequence of argument types, beginning with the one whose length is A1 's minimum arity , adds a name (...) method overload to the extension class. Each overload generated invokes a1's call-expression with P , using a copy of a1's call policies. If the longest valid prefix of A1 contains N types and a1 holds M keywords, an initial sequence of the keywords are used for all but the first N - M arguments of each overload.

Otherwise, Fn must be [derived from] object , and a1-a2, if supplied, may be selcted in any order from the first two rows of the table below. To be useful, fn should be callable .

name is an ntbs which conforms to Python's identifier naming rules , and corresponds to a method whose overloads have all been defined.

Replaces the existing named attribute x with the result of invoking staticmethod ( x ) in Python. Specifies that the corresponding method is static and therefore no object instance will be passed to it. This is equivalent to the Python statement:

Attempting to invoke def(name,...) after invoking staticmethod(name) will raise a RuntimeError.

Adds a Python special method as described here .

name is an ntbs which conforms to Python's identifier naming rules .

Converts u to Python and adds it to the attribute dictionary of the extension class:

name is an ntbs which conform to Python's identifier naming rules .

Creates a new Python property class instance, passing object ( fget ) (and object ( fset ) in the second form) with an (optional) docstring doc to its constructor, then adds that property to the Python class object under construction with the given attribute name.

Allows users to easily expose functions that can be invoked from Python with attribute access syntax.

Creates a Boost.Python.StaticProperty object, passing object ( fget ) (and object ( fset ) in the second form) to its constructor, then adds that property to the Python class under construction with the given attribute name. StaticProperty is a special subclass of Python's property class which can be called without an initial self argument.

Allows users to easily expose functions that can be invoked from Python with static attribute access syntax.

name is an ntbs which conforms to Python's identifier naming rules . doc is also an ntbs .

respectively.

Allows users to easily expose a class' data member or free variable such that it can be inspected from Python with a natural syntax.

Allows users to easily expose a class' data or free variable member such that it can be inspected and set from Python with a natural syntax.

PickleSuite must be publically derived from pickle_suite .

Defines a legal combination of the special attributes and methods: __getinitargs__, __getstate__, __setstate__, __getstate_manages_dict__, __safe_for_unpickling__, __reduce__

Provides an easy to use high-level interface for establishing complete pickle support for the wrapped class. The user is protected by compile-time consistency checks.

Defines the __reduce__ method and the __safe_for_unpickling__ attribute.

Light-weight alternative to def_pickle(). Enables implementation of pickle support from Python.

Class template bases<T1, T2, ...TN>

An MPL sequence which can be used in class_<...> instantiations indicate a list of base classes.

Class template bases synopsis

Given a C++ class declaration:

A corresponding Boost.Python extension class can be created with:

add_property boost python

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to translate caffe python api from Boost.Python to pybind11 #1484

@fireae

fireae commented Aug 6, 2018

@bmerry

bmerry commented Aug 13, 2018

Sorry, something went wrong.

fireae commented Aug 14, 2018

@fireae

No branches or pull requests

@fireae

Interoperation between pybind11 and Boost.Python #

pybind11 and Boost.Python are two different tools offering similar capabilities to wrap between C++ and Python and to extend and embed Python. They can wrap the C++ constructs to Python, and allow C++ code to invoke Python code. At the center of the capabilities lies the system for bi-directional conversion between C++ and Python. By using both tools simultaneously, we have delicate 4-way conversion:

Pass pybind11-wrapped (C++) objects to Boost.Python-wrapped (C++) functions.

Return pybind11-wrapped (C++) objects from Boost.Python-wrapped (C++) functions.

Pass Boost.Python-wrapped (C++) objects to pybind11-wrapped (C++) functions.

Return Boost.Python-wrapped (C++) objects from pybind11-wrapped (C++) functions.

Why Mixing Two Wrapping Systems? #

It is very rare to need to use pybind11 and Boost.Python together. When it happens, I guess you either use Boost.Python already and want or need to use pybind11 to replace it, or need to combine two systems that unfortunately chose the different tools.

If you are creating a new wrapping layer, choose pybind11 , because modern C++ is the way to go, and pybind11 offers much cleaner and powerful API. Boost.Python is a good tool, but you usually do not want the complexity incorporated in Boost, as it is described by the pybind11 project:

The main issue with Boost.Python—and the reason for creating such a similar project—is Boost.

I think you only need to consider Boost.Python when you cannot use C++11.

Conversion for pybind11 and Boost.Python #

pybind11 and Boost.Python use different design to convert between C++ and Python. pybind11 uses its “ casters ” while Boost.Python uses its “ converters ”. When wrapping using pybind11 and Boost.Python, the tools will create the “casters” and “converters” behind the scenes, so that you do not need to worry about the conversion of the C++ objects they wrap to and from Python. We cannot expect the tools to automatically recognize each other, and need to do something special in the “casters” and “converters”.

Let’s write two classes: ItemPyb ( Class to be wrapped by pybind11 ) and ItemBpy ( Class to be wrapped by Boost.Python ). The two classes may return new instances of their own type and the other type, as shown in the highlighted lines.

pybind11 Caster for Boost.Python #

By default, pybind11 does not know what to do with a class that is wrapped by Boost.Python. So we need to create pybind11 casters for the Boost.Python-wrapped classes. In the highlighted lines, I copy code from the macro PYBIND11_TYPE_CASTER to make it work.

The pybind11 casters is the template specialization created with the new macro PYBOOST11_TYPE_CASTER . To “use” it, insert the macro to create the specialization in the pybind11-wrapped module:

The pybind11 library will automatically find it during runtime to perform the to- and from-Python conversion.

See pyboost11.hpp and modpyb.cpp for the full code.

Boost.Python Converter for pybind11 #

Boost.Python does not know anything about pybind11, either. So we need to create Boost.Python converters for the pybind11-wrapped classes. The converter supports both to-python and from-python conversion.

Boost.Python requires us to register the conversion code using its API during runtime. The following code needs to be invoked from a Boost.Python-wrapped module:

See pyboost11.hpp and modbpy.cpp for the full code.

The 4-Way Conversion #

To this point, we made two helpers. One is the pybind11 caster that knows how to convert Boost.Python-wrapped classes to and from Python. The other is the Boost.Python converter that knows how to convert pybind11-wrapped classes to and from Python. We can test how the helpers work. In the test classes ItemPyb and ItemBpy there are the setter functions to help testing:

ItemPyb is wrapped to Python using the standard pybind11 class wrapper:

Similarly, ItemBpy is wrapped to Python using the standard Boost.Python class wrapper:

The full code of the wrappers can be found in modpyb.cpp and modbpy.cpp .

Test an ItemPyb that takes and makes another ItemPyb :

Test the ItemPyb to take and make an ItemBpy :

Similarly, test an ItemBpy that takes and makes an ItemPby :

Test the ItemBpy to take and make another ItemBpy :

Ownership #

The 4-way conversion works fine except that the item classes are passed by value. We will see the conversion also works well when the classes are managed by shared pointers.

We need new item classes and the containers to hold them. Let us start to build the test infrastructure with the item classes. ItemPybSS ( Class managed by shared pointer and wrapped by pybind11 ):

Then we build ItemBpyBS ( Class managed by shared pointer and wrapped by Boost.Python ). To make it work with older version of Boost.Python, we used boost::shared_ptr instead of std::shared_ptr .

Because the support for std::shared_ptr is relatively new (see https://www.boost.org/users/history/version_1_63_0.html ), boost::shared_ptr support in Boost.Python is more stable.

After having the item classes, we build the container classes. The containers will hold the above two item classes as well as the two pass-by-value item classes we had previously. The container classes will provide member functions to take the ownership of the item objects managed by shared pointer. ContainerPyb ( Container that is wrapped by pybind11 ):

ContainerBpy ( Container that is wrapped by Boost.Python ):

Wrap the Containers #

The pybind11 wrappers:

The Boost.Python wrappers:

Test the Containers #

Now we can check what will happen in the Python. First we check ContainerPyb :

ContainerBpy will work the same:

Take the 4-way conversion in pyboost11.hpp if you think it is useful. It is not yet tested thoroughly, and I have not figured out all the details in the conversion. Any feedbacks are welcome.

Reference Code #

Boost.Python(一)

小编将Boost.Python官方文档的内容梳理补充给大家,细节详见官方文档。

The Boost Python Library is a framework for interfacing Python and C++. It allows you to quickly and seamlessly expose C++ classes functions and objects to Python, and vice-versa, using no special tools -- just your C++ compiler. It is designed to wrap C++ interfaces non-intrusively, so that you should not have to change the C++ code at all in order to wrap it, making Boost.Python ideal for exposing 3rd-party libraries to Python.

The library's use of advanced metaprogramming techniques simplifies its syntax for users, so that wrapping code takes on the look of a kind of declarative interface definition language (IDL).

The Boost.Python‘s compile need MSVC and Python.

using namespace std;

char const * greet()

return"hello,world";

BOOST_PYTHON_MODULE(hello_ext)

using namespace boost::python;

def("greet",greet);

importhello_ext

printhello_ext.greet()

Here, we wrote a C++ class wrapper that exposes the member functions greet and set. Now, after building our module as a shared library, we may use our class World in Python.

struct World

voidset(string msg) { this->msg = msg; }

string greet() {returnmsg; }

string msg;

BOOST_PYTHON_MODULE(hello)

class_("World")

.def("greet",&World::greet)

.def("set", &World::set);

World(string msg):msg(msg){}

World(double a,double b):a(a),b(b) {}

double sum_s() {returna + b; }

class_("World",init())

.def(init())

.def("set",&World::set)

.def("sum_s",&World::sum_s);

importhello

planet = hello.World(5,6)

planet2 = hello.World("hollo world")

printplanet.sum_s()

printplanet2.greet()

init() exposes the constructor taking in a std::string (in Python, constructors are spelled ""__init__"").

On the other hand, if we do not wish to expose any constructors at all, we may use no_init instead:

class_("Abstract",no_init)

Var(string name):name(name),value(){}

string const name;

floatvalue;

BOOST_PYTHON_MODULE(hello_var)

class_("Var",init())

.def_readonly("name",&Var::name)

.def_readwrite("value",&Var::value);

Data members may also be exposed to Python so that they can be accessed as attributes of the corresponding Python class. Each data member that we wish to be exposed may be regarded as read-only or read-write.

floatget() const {returnval; }

voidset(floatval) { this->val = val; }

BOOST_PYTHON_MODULE(hello_num)

class_("Num")

.add_property("rovalue",&Num::get)

.add_property("value",&Num::get,&Num::set);

>>> x = Num()

>>> x.value =3.14

>>> x.value,x.rovalue

(3.14,3.14)

>>> x.rovalue =2.17# error!

In C++, Well designed classes that take advantage of encapsulation hide the class' data members. The only way to access the class' data is through access (getter/setter) functions.

However, in Python attribute access is fine; it doesn't neccessarily break encapsulation to let users handle attributes directly, because the attributes can just be a different syntax for a method call.

struct Base

virtual ~Base() {};

virtual string getName() {return"Base"; }

struct Derived : Base

string getName() {return"Derived"; }

void b(Base *base) { cout getName()

void d(Derived *derived) { cout getName()

Base* factory() {returnnew Derived; }

BOOST_PYTHON_MODULE(hello_derived)

//wrap the baseclassBase

class_("Base")

.def("getName",&Base::getName)

.def_readwrite("str",&Base::str);

//wrap theclasshierarchies Derivedand

//inform Boost.Python of the inheritance relationship between Derivedandits baseclassBase.

class_ >("Derived")

.def("getName",&Derived::getName)

.def_readwrite("str",&Derived::str);

def("b",b);

def("d",d);

//use return_value_policy to instruct Python to adopt the pointer to Base

//andhold the instanceina new Python Baseobjectuntil the the Pythonobjectisdestroyed.

def("factory",factory,return_value_policy());

importhello_derived

derive = hello_derived.factory()

hello_derived.d(derive)

One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. It is not ideal to add anything to our class Base. Yet, when you have a virtual function that's going to be overridden in Python and called polymorphically from C++, we'll need to add some scaffoldings to make things work properly. What we'll do is write a class wrapper that derives from Base that will unintrusively hook into the virtual functions so that a Python override may be called:

virtual ~Base() {}

virtualintf() =;

struct BaseWrap : Base,wrapper

returnthis->get_override("f")();

We've seen in the previous section how classes with pure virtual functions are wrapped using Boost.Python'sclass wrapperfacilities. If we wish to wrap non-pure-virtual functions instead, the mechanism is a bit different.

//类的虚函数,实现的功能是:可以编写Python类,来继承C++类

virtualintf() {return; };

if(override f = this->get_override("f"))

returnf(); //如果函数进行重载了,则返回重载的

returnBase::f(); //否则返回基类的

intdefault_f() {returnthis->Base::f(); }

BOOST_PYTHON_MODULE(hello_virtual)

.def("f",&Base::f,&BaseWrap::default_f);

importhello_virtual

base = hello_virtual.Base()

# 定义派生类,继承C++类

classDerived(hello_virtual.Base):

deff(self):

derived = Derived()

printbase.f()

printderived.f()

基于Ubuntu及py3的CTP接口编译——Boost编译

基于ubuntu及py3的ctp接口编译——anaconda环境, vn.py——行情api封装的测试, vn.py——api封装的编译, vn.py——datarecorder引擎, vn.py-聊聊mongodb呗, dlib 19.9的巨大进步,安装无须boost.python, 人工智能语言python中的库是如何应用的, 一茶一世界,一壶一乾坤.

腾讯云开发者公众号二维码

add_property boost python

Copyright © 2013 - 2023 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有

深圳市腾讯计算机系统有限公司 ICP备案/许可证号: 粤B2-20090059 深公网安备号 44030502008569

腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287

add_property boost python

Advanced C++ / Python integration with Boost.Python (Part 3)

In this final part of the series I’m going to look at one further way we can use Boost.Python to help when using a C++ class within Python.

In the previous part we built a wrapper for a C++ class, exposing a number of class methods to Python.

However, in Python, it’s quite typical for a class to use  properties  as well as methods.

So to begin – let’s take a moment to look at properties within the context of classes in Python.

For example, if we had a Python class which looks like this:

We could then use it, something like this:

Whilst this works, we might reasonably say that the necessity to use  getter and  setter functions directly is not especially  Pythonic – as it’s not how most built-in objects behave.

Instead we’d expect to be able to use it more like this:

We can do exactly this; if we use properties…

We just need to make a couple of changes to our Python code to enable this.

Note that substantively the code is unchanged; but we have renamed our two methods (giving them both the same name) and we’ve added two  decorators – setting up the property (and thus implicitly the  getter for that) and the explicit setup for the  setter method.

Running this version in conjunction with the second usage example, we have a much more Pythonic implementation.

So the question is – can we do this when we’re wrapping a C++ class, with Boost.Python?

Well, of course the answer is yes!

Last time around we finished up with a Python class created using this call of the  BOOST_PYTHON_MODULE macro.

We’ll leave the explicit way of setting the data with three discrete values (via set_data() ) as-is, as that’s a slightly different use-case; but wouldn’t it be nice if we could use the import and export methods as the setter and getter of a bytes property?

It turns out that doing this is trivially easy. All we do is remove the .def lines for the importer  and exporter methods; and replace them with one .add_property() line…

Now we can use the new bytes property from within Python by using:

That concludes my brief introduction on how to use Boost.Python to wrap your existing C++ code for use in Python. I hope you’ve found it useful or interesting.

Share this:

Leave a reply cancel reply.

Your email address will not be published. Required fields are marked *

Save my name, email, and website in this browser for the next time I comment.

This site uses Akismet to reduce spam. Learn how your comment data is processed .

Filed under: C++ , Python - @ December 22, 2017 16:00

.

IMAGES

  1. Python Property

    add_property boost python

  2. Introduction to XGBoost in Python

    add_property boost python

  3. Python property () function

    add_property boost python

  4. Simple Boost converter designing program using python

    add_property boost python

  5. Python Property()

    add_property boost python

  6. Boost.Python: C++ and Python Integration

    add_property boost python

VIDEO

  1. EasyRenz

  2. how to add listings in mytoletindia.com

  3. how to add property list in HRMS // fill up of property in HRMS 2022 // mobile online fill up

  4. How To Get Your Pistol Brace (SBR) Tax Stamp In a Trust For Free

  5. Python Optional Parameters #pythonforbeginners #pythonprogramming #pythontutorial #programming

  6. Python :Why shouldn't I use PyPy over CPython if PyPy is 6.3 times faster?(5solution)

COMMENTS

  1. Exposing Classes

    Wrapping our Num class using Boost.Python: class_<Num>("Num") .add_property

  2. Exposing Classes

    Num class using Boost.Python: class_<Num>("Num") .add_property("rovalue"

  3. Boost python howto

    This is how the boost::python unit tests implement a raw constructor, see test/raw_ctor.cpp. ... .add_property("a", &C::getA, &C::setA).

  4. Strange behavior of add_property in Boost.Python

    I met a strange behavior when using add_property of Boost.Python. Here is the example codes, it simply add two properties (read-only

  5. Chapter 2. High Level Components

    D& d); // property creation template <class Get> void add_property(char

  6. Boost::Python

    .add_property("value", &A::get, &A::set).

  7. Is it possible to translate caffe python api from Boost.Python ...

    I am now facing some problems. bp::class_ , boost::noncopyable>( "Blob", bp::no_init) .add_property("shape", bp::make_function( static_cast

  8. Interoperation between pybind11 and Boost.Python

    Boost.Python is a good tool, but you usually do not want the complexity ... .add_property ( "bpy" , bpy::make_function ( &ContainerBpy::bpy

  9. Boost.Python(一)

    The Boost Python Library is a framework for interfacing Python and C++. ... .add_property("value",&Num::get,&Num::set);. } python:.

  10. Advanced C++ / Python integration with Boost.Python (Part 3)

    def lines for the importer and exporter methods; and replace them with one .add_property() line…

  11. <boost/python/class.hpp>, <boost/python/class_fwd.hpp>

    <boost/python/class.hpp> defines the interface through which users expose their C++ classes to Python. It declares the class_ class template