Now let's expose a C++ class to Python: {{{ #include #include namespace { // Avoid cluttering the global namespace. // A friendly class. class hello { public: hello(const std::string& country) { this->country = country; } std::string greet() const { return "Hello from " + country; } private: std::string country; }; // A function taking a hello object as an argument. std::string invite(const hello& w) { return w.greet() + "! Please come soon!"; } } }}} To expose the class, we use a ''class_'' builder. Class member functions are exposed by using the ''def()'' member: {{{ #include using namespace boost::python; BOOST_PYTHON_MODULE(getting_started2) { // Create the Python type object for our extension class and define __init__ function. class_("hello", init()) .def("greet", &hello::greet) // Add a regular member function. .def("invite", invite) // Add invite() as a regular function to the module. ; def("invite", invite); // Even better, invite() can also be made a member of module!!! } }}} Now we can use the class normally from Python: {{{ >>> from getting_started2 import * >>> hi = hello('California') >>> hi.greet() 'Hello from California' >>> invite(hi) 'Hello from California! Please come soon!' >>> hi.invite() 'Hello from California! Please come soon!' }}} Notes: * We expose the class' constructor by calling ''def()'' on the ''class_'' builder with an argument whose type is ''constructor'', where ''params'' matches the list of constructor argument types; * Regular member functions are defined by calling ''def()'' with a member function pointer and its Python name; * Any function added to a class whose initial argument matches the class (or any base) will act like a member function in Python. * To define a nested class, just place class_<> builder inside another class `scope`: {{{ BOOST_PYTHON_MODULE(nested_ext) { using namespace boost::python; // Establish X as the current scope. scope x_class( class_("X", init()) .def(str(self)) ); // Y will now be defined in the current scope class_("Y", init()) .def(str(self)) ; } }}} We can even make a subclass of hello.world: {{{ >>> class wordy(hello): ... def greet(self): ... return hello.greet(self) + ', where the weather is fine' ... >>> hi2 = wordy('Florida') >>> hi2.greet() 'Hello from Florida, where the weather is fine' >>> invite(hi2) 'Hello from Florida! Please come soon!' }}} Pretty cool! You can't do that with an ordinary Python extension type! Of course, you may now have a slightly empty feeling in the pit of your little pythonic stomach. Perhaps you wanted to see the following ''wordy'' invitation: {{{ 'Hello from Florida, where the weather is fine! Please come soon!' }}} After all, ''invite'' calls ''hello::greet()'', and you reimplemented that in your Python subclass, ''wordy''. In [[boost.python/OverridableVirtualFunctions|the next section]] we'll make ''greet'' virtual, and we'll see how to make C++ code see our overrides from Python. It is important to note that boost::python will not allow you to make dynamic type casts (through polymorphism) if the function/method is considered "unsafe". That means that an appropriate method-wrapper will not be created for functions that execute potentially exception-generating code where exceptions do not have python mappings. Let's have a look at an example: We make a base class we can derive from: {{{ class Base { public: boost::python::list list; virtual void x() = 0; }; }}} And derive from that in the classic way, implementing the function x() in such a way that it uses unprotected boost::python::extract instances without catching potential exceptions: {{{ class Derive : public Base { public: virtual void x() { int y = boost::python::extract(list[0])(); } }; }}} Exporting the classes like this: {{{ class BaseWrap : public Base, public wrapper { public: virtual void x() { this->get_override("x")(); } }; class_("Base") .def("x", boost::python::pure_virtual(&Base::x)) ; class_ >("Derive"); }}} Will generate the following error whenever you try to cast an instance of Derive to Base*: {{{ TypeError: No registered converter was able to produce a C++ rvalue of type int from this Python object of type method-wrapper }}} What to do? Simply use try{}catch(){} blocks around any boost::python code that can produce an exception, such as the extract operation.