Differences between revisions 1 and 2
Revision 1 as of 2002-09-26 18:52:08
Size: 2822
Editor: MikeRovner
Comment:
Revision 2 as of 2002-09-26 23:50:40
Size: 3203
Editor: MikeRovner
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
Now let's expose a C++ class to Python:  Now let's expose a C++ class to Python:
Line 24: Line 24:
To expose the class, we use a ''class_'' builder. Class member functions are exposed by using the ''def()'' member:  To expose the class, we use a ''class_'' builder. Class member functions are exposed by using the ''def()'' member:
Line 38: Line 38:
    
Line 42: Line 42:
Now we can use the class normally from Python:  Now we can use the class normally from Python:
Line 54: Line 54:
 * We expose the class' constructor by calling ''def()'' on the ''class_'' builder with an argument whose type is ''constructor<params>'', 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 '''???'''.
 * We expose the class' constructor by calling ''def()'' on the ''class_'' builder with an argument whose type is ''constructor<params>'', 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_INIT(nested_ext)
{
    using namespace boost::python;
Line 59: Line 62:
We can even make a subclass of hello.world:     // Establish X as the current scope.
    scope x_class(
        class_<X>("X", init<int>())
           .def(str(self))
        );

    // Y will now be defined in the current scope
    class_<Y>("Y", init<int>())
        .def(str(self))
        ;
}
}}}

We can even make a subclass of hello.world:
Line 71: Line 87:
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:  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:

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

#include <iostream>
#include <string>

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 <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/def.hpp>
using namespace boost::python;

BOOST_PYTHON_MODULE_INIT(getting_started2)
{
    // Create the Python type object for our extension class and define __init__ function.
    class_<hello>("hello", init<std::string>())
        .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<params>, 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_INIT(nested_ext)
    {
        using namespace boost::python;
    
        // Establish X as the current scope.
        scope x_class(
            class_<X>("X", init<int>())
               .def(str(self))
            );
    
        // Y will now be defined in the current scope
        class_<Y>("Y", init<int>())
            .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.

boost.python/ExportingClasses (last edited 2008-11-15 14:01:19 by localhost)

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