Boost.Python is an open source C++ library which provides a concise
+IDL-like interface for binding C++ classes and functions to
+Python. Leveraging the full power of C++ compile-time introspection
+and of recently developed metaprogramming techniques, this is achieved
+entirely in pure C++, without introducing a new syntax.
+Boost.Python's rich set of features and high-level interface make it
+possible to engineer packages from the ground up as hybrid systems,
+giving programmers easy and coherent access to both the efficient
+compile-time polymorphism of C++ and the extremely convenient run-time
+polymorphism of Python.
Python and C++ are in many ways as different as two languages could
+be: while C++ is usually compiled to machine-code, Python is
+interpreted. Python's dynamic type system is often cited as the
+foundation of its flexibility, while in C++ static typing is the
+cornerstone of its efficiency. C++ has an intricate and difficult
+compile-time meta-language, while in Python, practically everything
+happens at runtime.
+
Yet for many programmers, these very differences mean that Python and
+C++ complement one another perfectly. Performance bottlenecks in
+Python programs can be rewritten in C++ for maximal speed, and
+authors of powerful C++ libraries choose Python as a middleware
+language for its flexible system integration capabilities.
+Furthermore, the surface differences mask some strong similarities:
+
+
'C'-family control structures (if, while, for...)
+
Support for object-orientation, functional programming, and generic
+programming (these are both multi-paradigm programming languages.)
+
Comprehensive operator overloading facilities, recognizing the
+importance of syntactic variability for readability and
+expressivity.
+
High-level concepts such as collections and iterators.
+
High-level encapsulation facilities (C++: namespaces, Python: modules)
+to support the design of re-usable libraries.
+
Exception-handling for effective management of error conditions.
+
C++ idioms in common use, such as handle/body classes and
+reference-counted smart pointers mirror Python reference semantics.
+
+
Given Python's rich 'C' interoperability API, it should in principle
+be possible to expose C++ type and function interfaces to Python with
+an analogous interface to their C++ counterparts. However, the
+facilities provided by Python alone for integration with C++ are
+relatively meager. Compared to C++ and Python, 'C' has only very
+rudimentary abstraction facilities, and support for exception-handling
+is completely missing. 'C' extension module writers are required to
+manually manage Python reference counts, which is both annoyingly
+tedious and extremely error-prone. Traditional extension modules also
+tend to contain a great deal of boilerplate code repetition which
+makes them difficult to maintain, especially when wrapping an evolving
+API.
+
These limitations have lead to the development of a variety of wrapping
+systems. SWIG is probably the most popular package for the
+integration of C/C++ and Python. A more recent development is SIP,
+which was specifically designed for interfacing Python with the Qt
+graphical user interface library. Both SWIG and SIP introduce their
+own specialized languages for customizing inter-language bindings.
+This has certain advantages, but having to deal with three different
+languages (Python, C/C++ and the interface language) also introduces
+practical and mental difficulties. The CXX package demonstrates an
+interesting alternative. It shows that at least some parts of
+Python's 'C' API can be wrapped and presented through a much more
+user-friendly C++ interface. However, unlike SWIG and SIP, CXX does
+not include support for wrapping C++ classes as new Python types.
+
The features and goals of Boost.Python overlap significantly with
+many of these other systems. That said, Boost.Python attempts to
+maximize convenience and flexibility without introducing a separate
+wrapping language. Instead, it presents the user with a high-level
+C++ interface for wrapping C++ classes and functions, managing much of
+the complexity behind-the-scenes with static metaprogramming.
+Boost.Python also goes beyond the scope of earlier systems by
+providing:
+
+
Support for C++ virtual functions that can be overridden in Python.
+
Comprehensive lifetime management facilities for low-level C++
+pointers and references.
+
Support for organizing extensions as Python packages,
+with a central registry for inter-language type conversions.
+
A safe and convenient mechanism for tying into Python's powerful
+serialization engine (pickle).
+
Coherence with the rules for handling C++ lvalues and rvalues that
+can only come from a deep understanding of both the Python and C++
+type systems.
+
+
The key insight that sparked the development of Boost.Python is that
+much of the boilerplate code in traditional extension modules could be
+eliminated using C++ compile-time introspection. Each argument of a
+wrapped C++ function must be extracted from a Python object using a
+procedure that depends on the argument type. Similarly the function's
+return type determines how the return value will be converted from C++
+to Python. Of course argument and return types are part of each
+function's type, and this is exactly the source from which
+Boost.Python deduces most of the information required.
+
This approach leads to user guided wrapping: as much information is
+extracted directly from the source code to be wrapped as is possible
+within the framework of pure C++, and some additional information is
+supplied explicitly by the user. Mostly the guidance is mechanical
+and little real intervention is required. Because the interface
+specification is written in the same full-featured language as the
+code being exposed, the user has unprecedented power available when
+she does need to take control.
The primary goal of Boost.Python is to allow users to expose C++
+classes and functions to Python using nothing more than a C++
+compiler. In broad strokes, the user experience should be one of
+directly manipulating C++ objects from Python.
+
However, it's also important not to translate all interfaces too
+literally: the idioms of each language must be respected. For
+example, though C++ and Python both have an iterator concept, they are
+expressed very differently. Boost.Python has to be able to bridge the
+interface gap.
+
It must be possible to insulate Python users from crashes resulting
+from trivial misuses of C++ interfaces, such as accessing
+already-deleted objects. By the same token the library should
+insulate C++ users from low-level Python 'C' API, replacing
+error-prone 'C' interfaces like manual reference-count management and
+raw PyObject pointers with more-robust alternatives.
+
Support for component-based development is crucial, so that C++ types
+exposed in one extension module can be passed to functions exposed in
+another without loss of crucial information like C++ inheritance
+relationships.
+
Finally, all wrapping must be non-intrusive, without modifying or
+even seeing the original C++ source code. Existing C++ libraries have
+to be wrappable by third parties who only have access to header files
+and binaries.
And now for a preview of Boost.Python, and how it improves on the raw
+facilities offered by Python. Here's a function we might want to
+expose:
+
+char const* greet(unsigned x)
+{
+ static char const* const msgs[] = { "hello", "Boost.Python", "world!" };
+
+ if (x > 2)
+ throw std::range_error("greet: index out of range");
+
+ return msgs[x];
+}
+
+
To wrap this function in standard C++ using the Python 'C' API, we'd
+need something like this:
+
+extern "C" // all Python interactions use 'C' linkage and calling convention
+{
+ // Wrapper to handle argument/result conversion and checking
+ PyObject* greet_wrap(PyObject* args, PyObject * keywords)
+ {
+ int x;
+ if (PyArg_ParseTuple(args, "i", &x)) // extract/check arguments
+ {
+ char const* result = greet(x); // invoke wrapped function
+ return PyString_FromString(result); // convert result to Python
+ }
+ return 0; // error occurred
+ }
+
+ // Table of wrapped functions to be exposed by the module
+ static PyMethodDef methods[] = {
+ { "greet", greet_wrap, METH_VARARGS, "return one of 3 parts of a greeting" }
+ , { NULL, NULL, 0, NULL } // sentinel
+ };
+
+ // module initialization function
+ DL_EXPORT init_hello()
+ {
+ (void) Py_InitModule("hello", methods); // add the methods to the module
+ }
+}
+
+
Now here's the wrapping code we'd use to expose it with Boost.Python:
+
+#include <boost/python.hpp>
+using namespace boost::python;
+BOOST_PYTHON_MODULE(hello)
+{
+ def("greet", greet, "return one of 3 parts of a greeting");
+}
+
+
and here it is in action:
+
+>>> import hello
+>>> for x in range(3):
+... print hello.greet(x)
+...
+hello
+Boost.Python
+world!
+
+
Aside from the fact that the 'C' API version is much more verbose,
+it's worth noting a few things that it doesn't handle correctly:
+
+
The original function accepts an unsigned integer, and the Python
+'C' API only gives us a way of extracting signed integers. The
+Boost.Python version will raise a Python exception if we try to pass
+a negative number to hello.greet, but the other one will proceed
+to do whatever the C++ implementation does when converting an
+negative integer to unsigned (usually wrapping to some very large
+number), and pass the incorrect translation on to the wrapped
+function.
+
That brings us to the second problem: if the C++ greet()
+function is called with a number greater than 2, it will throw an
+exception. Typically, if a C++ exception propagates across the
+boundary with code generated by a 'C' compiler, it will cause a
+crash. As you can see in the first version, there's no C++
+scaffolding there to prevent this from happening. Functions wrapped
+by Boost.Python automatically include an exception-handling layer
+which protects Python users by translating unhandled C++ exceptions
+into a corresponding Python exception.
+
A slightly more-subtle limitation is that the argument conversion
+used in the Python 'C' API case can only get that integer x in
+one way. PyArg_ParseTuple can't convert Python long objects
+(arbitrary-precision integers) which happen to fit in an unsigned
+int but not in a signed long, nor will it ever handle a
+wrapped C++ class with a user-defined implicit operator unsigned
+int() conversion. Boost.Python's dynamic type conversion
+registry allows users to add arbitrary conversion methods.
Although this code has a certain pythonic familiarity, people
+sometimes find the syntax bit confusing because it doesn't look like
+most of the C++ code they're used to. All the same, this is just
+standard C++. Because of their flexible syntax and operator
+overloading, C++ and Python are great for defining domain-specific
+(sub)languages
+(DSLs), and that's what we've done in Boost.Python. To break it down:
+
+class_<World>("World")
+
+
constructs an unnamed object of type class_<World> and passes
+"World" to its constructor. This creates a new-style Python class
+called World in the extension module, and associates it with the
+C++ type World in the Boost.Python type conversion registry. We
+might have also written:
+
+class_<World> w("World");
+
+
but that would've been more verbose, since we'd have to name w
+again to invoke its def() member function:
+
+w.def("greet", &World::greet)
+
+
There's nothing special about the location of the dot for member
+access in the original example: C++ allows any amount of whitespace on
+either side of a token, and placing the dot at the beginning of each
+line allows us to chain as many successive calls to member functions
+as we like with a uniform syntax. The other key fact that allows
+chaining is that class_<> member functions all return a reference
+to *this.
It's occasionally useful to be able to break down the components of a
+Boost.Python class wrapper in this way, but the rest of this article
+will stick to the terse syntax.
+
For completeness, here's the wrapped class in use:
Since our World class is just a plain struct, it has an
+implicit no-argument (nullary) constructor. Boost.Python exposes the
+nullary constructor by default, which is why we were able to write:
+
+>>> planet = hello.World()
+
+
However, well-designed classes in any language may require constructor
+arguments in order to establish their invariants. Unlike Python,
+where __init__ is just a specially-named method, In C++
+constructors cannot be handled like ordinary member functions. In
+particular, we can't take their address: &World::World is an
+error. The library provides a different interface for specifying
+constructors. Given:
This does not result in adding attributes to the World instance
+__dict__, which can result in substantial memory savings when
+wrapping large data structures. In fact, no instance __dict__
+will be created at all unless attributes are explicitly added from
+Python. Boost.Python owes this capability to the new Python 2.2 type
+system, in particular the descriptor interface and property type.
+
In C++, publicly-accessible data members are considered a sign of poor
+design because they break encapsulation, and style guides usually
+dictate the use of "getter" and "setter" functions instead. In
+Python, however, __getattr__, __setattr__, and since 2.2,
+property mean that attribute access is just one more
+well-encapsulated syntactic tool at the programmer's disposal.
+Boost.Python bridges this idiomatic gap by making Python property
+creation directly available to users. If msg were private, we
+could still expose it as attribute in Python as follows:
The ability to write arithmetic operators for user-defined types has
+been a major factor in the success of both languages for numerical
+computation, and the success of packages like NumPy attests to the
+power of exposing operators in extension modules. Boost.Python
+provides a concise mechanism for wrapping operator overloads. The
+example below shows a fragment from a wrapper for the Boost rational
+number library:
The magic is performed using a simplified application of "expression
+templates" [VELD1995], a technique originally developed for
+optimization of high-performance matrix algebra expressions. The
+essence is that instead of performing the computation immediately,
+operators are overloaded to construct a type representing the
+computation. In matrix algebra, dramatic optimizations are often
+available when the structure of an entire expression can be taken into
+account, rather than evaluating each operation "greedily".
+Boost.Python uses the same technique to build an appropriate Python
+method object based on expressions involving self.
C++ inheritance relationships can be represented to Boost.Python by adding
+an optional bases<...> argument to the class_<...> template
+parameter list as follows:
When the class_<...> is created, Python type objects
+corresponding to Base1 and Base2 are looked up in
+Boost.Python's registry, and are used as bases for the new Python
+Derived type object, so methods exposed for the Python Base1
+and Base2 types are automatically members of the Derived
+type. Because the registry is global, this works correctly even if
+Derived is exposed in a different module from either of its
+bases.
+
C++ conversions from Derived to its bases are added to the
+Boost.Python registry. Thus wrapped C++ methods expecting (a
+pointer or reference to) an object of either base type can be
+called with an object wrapping a Derived instance. Wrapped
+member functions of class T are treated as though they have an
+implicit first argument of T&, so these conversions are
+neccessary to allow the base class methods to be called for derived
+objects.
+
+
Of course it's possible to derive new Python classes from wrapped C++
+class instances. Because Boost.Python uses the new-style class
+system, that works very much as for the Python built-in types. There
+is one significant detail in which it differs: the built-in types
+generally establish their invariants in their __new__ function, so
+that derived classes do not need to call __init__ on the base
+class before invoking its methods :
Because C++ object construction is a one-step operation, C++ instance
+data cannot be constructed until the arguments are available, in the
+__init__ function:
+
+>>> class D(SomeBoostPythonClass):
+... def __init__(self):
+... pass
+...
+>>> D().some_boost_python_method()
+Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+TypeError: bad argument type for built-in operation
+
+
This happened because Boost.Python couldn't find instance data of type
+SomeBoostPythonClass within the D instance; D's __init__
+function masked construction of the base class. It could be corrected
+by either removing D's __init__ function or having it call
+SomeBoostPythonClass.__init__(...) explicitly.
Deriving new types in Python from extension classes is not very
+interesting unless they can be used polymorphically from C++. In
+other words, Python method implementations should appear to override
+the implementation of C++ virtual functions when called through base
+class pointers/references from C++. Since the only way to alter the
+behavior of a virtual function is to override it in a derived class,
+the user must build a special derived class to dispatch a polymorphic
+class' virtual functions:
+
+//
+// interface to wrap:
+//
+class Base
+{
+ public:
+ virtual int f(std::string x) { return 42; }
+ virtual ~Base();
+};
+
+int calls_f(Base const& b, std::string x) { return b.f(x); }
+
+//
+// Wrapping Code
+//
+
+// Dispatcher class
+struct BaseWrap : Base
+{
+ // Store a pointer to the Python object
+ BaseWrap(PyObject* self_) : self(self_) {}
+ PyObject* self;
+
+ // Default implementation, for when f is not overridden
+ int f_default(std::string x) { return this->Base::f(x); }
+ // Dispatch implementation
+ int f(std::string x) { return call_method<int>(self, "f", x); }
+};
+
+...
+ def("calls_f", calls_f);
+ class_<Base, BaseWrap>("Base")
+ .def("f", &Base::f, &BaseWrap::f_default)
+ ;
+
The key element which allows overriding in Python is the
+call_method invocation, which uses the same global type
+conversion registry as the C++ function wrapping does to convert its
+arguments from C++ to Python and its return type from Python to C++.
+
Any constructor signatures you wish to wrap must be replicated with
+an initial PyObject* argument
+
The dispatcher must store this argument so that it can be used to
+invoke call_method
+
The f_default member function is needed when the function being
+exposed is not pure virtual; there's no other way Base::f can be
+called on an object of type BaseWrap, since it overrides f.
Admittedly, this formula is tedious to repeat, especially on a project
+with many polymorphic classes. That it is neccessary reflects some
+limitations in C++'s compile-time introspection capabilities: there's
+no way to enumerate the members of a class and find out which are
+virtual functions. At least one very promising project has been
+started to write a front-end which can generate these dispatchers (and
+other wrapping code) automatically from C++ headers.
+
Pyste is being developed by Bruno da Silva de Oliveira. It builds on
+GCC_XML, which generates an XML version of GCC's internal program
+representation. Since GCC is a highly-conformant C++ compiler, this
+ensures correct handling of the most-sophisticated template code and
+full access to the underlying type system. In keeping with the
+Boost.Python philosophy, a Pyste interface description is neither
+intrusive on the code being wrapped, nor expressed in some unfamiliar
+language: instead it is a 100% pure Python script. If Pyste is
+successful it will mark a move away from wrapping everything directly
+in C++ for many of our users. It will also allow us the choice to
+shift some of the metaprogram code from C++ to Python. We expect that
+soon, not only our users but the Boost.Python developers themselves
+will be "thinking hybrid" about their own code.
Serialization is the process of converting objects in memory to a
+form that can be stored on disk or sent over a network connection. The
+serialized object (most often a plain string) can be retrieved and
+converted back to the original object. A good serialization system will
+automatically convert entire object hierarchies. Python's standard
+pickle module is just such a system. It leverages the language's strong
+runtime introspection facilities for serializing practically arbitrary
+user-defined objects. With a few simple and unintrusive provisions this
+powerful machinery can be extended to also work for wrapped C++ objects.
+Here is an example:
Of course the cPickle module can also be used for faster
+processing.
+
Boost.Python's pickle_suite fully supports the pickle protocol
+defined in the standard Python documentation. Like a __getinitargs__
+function in Python, the pickle_suite's getinitargs() is responsible for
+creating the argument tuple that will be use to reconstruct the pickled
+object. The other elements of the Python pickling protocol,
+__getstate__ and __setstate__ can be optionally provided via C++
+getstate and setstate functions. C++'s static type system allows the
+library to ensure at compile-time that nonsensical combinations of
+functions (e.g. getstate without setstate) are not used.
+
Enabling serialization of more complex C++ objects requires a little
+more work than is shown in the example above. Fortunately the
+object interface (see next section) greatly helps in keeping the
+code manageable.
Experienced 'C' language extension module authors will be familiar
+with the ubiquitous PyObject*, manual reference-counting, and the
+need to remember which API calls return "new" (owned) references or
+"borrowed" (raw) references. These constraints are not just
+cumbersome but also a major source of errors, especially in the
+presence of exceptions.
+
Boost.Python provides a class object which automates reference
+counting and provides conversion to Python from C++ objects of
+arbitrary type. This significantly reduces the learning effort for
+prospective extension module writers.
+
Creating an object from any other type is extremely simple:
+
+object s("hello, world"); // s manages a Python string
+
+
object has templated interactions with all other types, with
+automatic to-python conversions. It happens so naturally that it's
+easily overlooked:
+
+object ten_Os = 10 * s[4]; // -> "oooooooooo"
+
+
In the example above, 4 and 10 are converted to Python objects
+before the indexing and multiplication operations are invoked.
+
The extract<T> class template can be used to convert Python objects
+to C++ types:
+
+double x = extract<double>(o);
+
+
If a conversion in either direction cannot be performed, an
+appropriate exception is thrown at runtime.
+
The object type is accompanied by a set of derived types
+that mirror the Python built-in types such as list, dict,
+tuple, etc. as much as possible. This enables convenient
+manipulation of these high-level types from C++:
This almost looks and works like regular Python code, but it is pure
+C++. Of course we can wrap C++ functions which accept or return
+object instances.
Because of the practical and mental difficulties of combining
+programming languages, it is common to settle a single language at the
+outset of any development effort. For many applications, performance
+considerations dictate the use of a compiled language for the core
+algorithms. Unfortunately, due to the complexity of the static type
+system, the price we pay for runtime performance is often a
+significant increase in development time. Experience shows that
+writing maintainable C++ code usually takes longer and requires far
+more hard-earned working experience than developing comparable Python
+code. Even when developers are comfortable working exclusively in
+compiled languages, they often augment their systems by some type of
+ad hoc scripting layer for the benefit of their users without ever
+availing themselves of the same advantages.
+
Boost.Python enables us to think hybrid. Python can be used for
+rapidly prototyping a new application; its ease of use and the large
+pool of standard libraries give us a head start on the way to a
+working system. If necessary, the working code can be used to
+discover rate-limiting hotspots. To maximize performance these can
+be reimplemented in C++, together with the Boost.Python bindings
+needed to tie them back into the existing higher-level procedure.
+
Of course, this top-down approach is less attractive if it is clear
+from the start that many algorithms will eventually have to be
+implemented in C++. Fortunately Boost.Python also enables us to
+pursue a bottom-up approach. We have used this approach very
+successfully in the development of a toolbox for scientific
+applications. The toolbox started out mainly as a library of C++
+classes with Boost.Python bindings, and for a while the growth was
+mainly concentrated on the C++ parts. However, as the toolbox is
+becoming more complete, more and more newly added functionality can be
+implemented in Python.
+
+
This figure shows the estimated ratio of newly added C++ and Python
+code over time as new algorithms are implemented. We expect this
+ratio to level out near 70% Python. Being able to solve new problems
+mostly in Python rather than a more difficult statically typed
+language is the return on our investment in Boost.Python. The ability
+to access all of our code from Python allows a broader group of
+developers to use it in the rapid development of new applications.
The first version of Boost.Python was developed in 2000 by Dave
+Abrahams at Dragon Systems, where he was privileged to have Tim Peters
+as a guide to "The Zen of Python". One of Dave's jobs was to develop
+a Python-based natural language processing system. Since it was
+eventually going to be targeting embedded hardware, it was always
+assumed that the compute-intensive core would be rewritten in C++ to
+optimize speed and memory footprint1. The project also wanted to
+test all of its C++ code using Python test scripts2. The only
+tool we knew of for binding C++ and Python was SWIG, and at the time
+its handling of C++ was weak. It would be false to claim any deep
+insight into the possible advantages of Boost.Python's approach at
+this point. Dave's interest and expertise in fancy C++ template
+tricks had just reached the point where he could do some real damage,
+and Boost.Python emerged as it did because it filled a need and
+because it seemed like a cool thing to try.
+
This early version was aimed at many of the same basic goals we've
+described in this paper, differing most-noticeably by having a
+slightly more cumbersome syntax and by lack of special support for
+operator overloading, pickling, and component-based development.
+These last three features were quickly added by Ullrich Koethe and
+Ralf Grosse-Kunstleve3, and other enthusiastic contributors arrived
+on the scene to contribute enhancements like support for nested
+modules and static member functions.
+
By early 2001 development had stabilized and few new features were
+being added, however a disturbing new fact came to light: Ralf had
+begun testing Boost.Python on pre-release versions of a compiler using
+the EDG front-end, and the mechanism at the core of Boost.Python
+responsible for handling conversions between Python and C++ types was
+failing to compile. As it turned out, we had been exploiting a very
+common bug in the implementation of all the C++ compilers we had
+tested. We knew that as C++ compilers rapidly became more
+standards-compliant, the library would begin failing on more
+platforms. Unfortunately, because the mechanism was so central to the
+functioning of the library, fixing the problem looked very difficult.
+
Fortunately, later that year Lawrence Berkeley and later Lawrence
+Livermore National labs contracted with Boost Consulting for support
+and development of Boost.Python, and there was a new opportunity to
+address fundamental issues and ensure a future for the library. A
+redesign effort began with the low level type conversion architecture,
+building in standards-compliance and support for component-based
+development (in contrast to version 1 where conversions had to be
+explicitly imported and exported across module boundaries). A new
+analysis of the relationship between the Python and C++ objects was
+done, resulting in more intuitive handling for C++ lvalues and
+rvalues.
+
The emergence of a powerful new type system in Python 2.2 made the
+choice of whether to maintain compatibility with Python 1.5.2 easy:
+the opportunity to throw away a great deal of elaborate code for
+emulating classic Python classes alone was too good to pass up. In
+addition, Python iterators and descriptors provided crucial and
+elegant tools for representing similar C++ constructs. The
+development of the generalized object interface allowed us to
+further shield C++ programmers from the dangers and syntactic burdens
+of the Python 'C' API. A great number of other features including C++
+exception translation, improved support for overloaded functions, and
+most significantly, CallPolicies for handling pointers and
+references, were added during this period.
+
In October 2002, version 2 of Boost.Python was released. Development
+since then has concentrated on improved support for C++ runtime
+polymorphism and smart pointers. Peter Dimov's ingenious
+boost::shared_ptr design in particular has allowed us to give the
+hybrid developer a consistent interface for moving objects back and
+forth across the language barrier without loss of information. At
+first, we were concerned that the sophistication and complexity of the
+Boost.Python v2 implementation might discourage contributors, but the
+emergence of Pyste and several other significant feature
+contributions have laid those fears to rest. Daily questions on the
+Python C++-sig and a backlog of desired improvements show that the
+library is getting used. To us, the future looks bright.
Boost.Python achieves seamless interoperability between two rich and
+complimentary language environments. Because it leverages template
+metaprogramming to introspect about types and functions, the user
+never has to learn a third syntax: the interface definitions are
+written in concise and maintainable C++. Also, the wrapping system
+doesn't have to parse C++ headers or represent the type system: the
+compiler does that work for us.
+
Computationally intensive tasks play to the strengths of C++ and are
+often impossible to implement efficiently in pure Python, while jobs
+like serialization that are trivial in Python can be very difficult in
+pure C++. Given the luxury of building a hybrid software system from
+the ground up, we can approach design with new confidence and power.
In retrospect, it seems that "thinking hybrid" from the
+ground up might have been better for the NLP system: the
+natural component boundaries defined by the pure python
+prototype turned out to be inappropriate for getting the
+desired performance and memory footprint out of the C++ core,
+which eventually caused some redesign overhead on the Python
+side when the core was moved to C++.
We also have some reservations about driving all C++
+testing through a Python interface, unless that's the only way
+it will be ultimately used. Any transition across language
+boundaries with such different object models can inevitably
+mask bugs.
[1]
+ Note that although we tested earlier versions of Boost.Python with Python
+ 2.2, and we don't think we've done anything
+ to break compatibility, this release of Boost.Python may not have been
+ tested with versions of Python earlier than 2.4, so we're not 100% sure
+ that python 2.2 and 2.3 are supported.
+
+ There are two basic models for combining C++ and Python:
+
+
+
+ extending,
+ in which the end-user launches the Python interpreter executable and
+ imports Python “extension modules” written in C++. Think of taking
+ a library written in C++ and giving it a Python interface so Python programmers
+ can use it. From Python, these modules look just like regular Python
+ modules.
+
+
+ embedding,
+ in which the end-user launches a program written in C++ that in turn
+ invokes the Python interpreter as a library subroutine. Think of adding
+ scriptability to an existing application.
+
+
+
+ The key distinction between extending and embedding is the location of the
+ C++ main()
+ function: in the Python interpreter executable, or in some other program,
+ respectively. Note that even when embedding Python in another program, extension
+ modules are often the best way to make C/C++ functionality accessible to
+ Python code, so the use of extension modules is really at the heart
+ of both models.
+
+
+ Except in rare cases, extension modules are built as dynamically-loaded libraries
+ with a single entry point, which means you can change them without rebuilding
+ either the other extension modules or the executable containing main().
+
+ If—instead of letting Boost.Build construct and link with the right libraries
+ automatically—you choose to use a pre-built Boost.Python library, you'll
+ need to think about which one to link with. The Boost.Python binary comes
+ in both static and dynamic flavors. Take care to choose the right flavor
+ for your application. [3]
+
+ The dynamic library is the safest and most-versatile choice:
+
+
+
+ A single copy of the library code is used by all extension modules
+ built with a given toolset. [4]
+
+
+ The library contains a type conversion registry. Because one registry
+ is shared among all extension modules, instances of a class exposed
+ to Python in one dynamically-loaded extension module can be passed
+ to functions exposed in another such module.
+
+ It might be appropriate to use the static Boost.Python library in any of
+ the following cases:
+
+
+
+ You are extending
+ python and the types exposed in your dynamically-loaded extension module
+ don't need to be used by any other Boost.Python extension modules,
+ and you don't care if the core library code is duplicated among them.
+
+
+ You are embedding
+ python in your application and either:
+
+
+ You are targeting a Unix variant OS other than MacOS or AIX,
+ where the dynamically-loaded extension modules can “see”
+ the Boost.Python library symbols that are part of the executable.
+
+
+ Or, you have statically linked some Boost.Python extension modules
+ into your application and you don't care if any dynamically-loaded
+ Boost.Python extension modules are able to use the types exposed
+ by your statically-linked extension modules (and vice-versa).
+
+
+
+
+
+
+
+
[3]
+ Information about how to identify the static and dynamic builds of Boost.Python
+ on Windows
+ / Unix
+ variants
+
+
[4]
+ Because of the way most *nix platforms share symbols among dynamically-loaded
+ objects, I'm not certain that extension modules built with different
+ compiler toolsets will always use different copies of the Boost.Python
+ library when loaded into the same Python instance. Not using different
+ libraries could be a good thing if the compilers have compatible
+ ABIs, because extension modules built with the two libraries would
+ be interoperable. Otherwise, it could spell disaster, since an extension
+ module and the Boost.Python library would have different ideas of
+ such things as class layout. I would appreciate someone doing the
+ experiment to find out what happens.
+
+ As described in the Boost.Build
+ Reference Manual, a file called user-config.jam in
+ your home directory is used to specify the tools and libraries available
+ to the build system. You may need to create or edit user-config.jam to
+ tell Boost.Build how to invoke Python, #include
+ its headers, and link with its libraries.
+
+
+
+
+
Note
+
+
+ If you are using a unix-variant OS and you ran Boost's configure
+ script, it may have generated a user-config.jam
+ for you. [2] If your configure/make sequence was successful and Boost.Python
+ binaries were built, your user-config.jam
+ file is probably already correct.
+
+
+
+ If you have one fairly “standard” python installation for your platform,
+ you might not need to do anything special to describe it. If you haven't
+ configured python in user-config.jam (and
+ you don't specify --without-python
+ on the Boost.Build command line), Boost.Build will automatically execute
+ the equivalent of
+
+
importtoolset:using;
+usingpython;
+
+
+ which automatically looks for Python in the most likely places. However,
+ that only happens when using the Boost.Python project file (e.g. when referred
+ to by another project as in the quickstart method). If instead you are linking
+ against separately-compiled Boost.Python binaries, you should set up a user-config.jam file
+ with at least the minimal incantation above.
+
+ If you have several versions of Python installed, or Python is installed
+ in an unusual way, you may want to supply any or all of the following optional
+ parameters to usingpython.
+
+
+
+
+
version
+
+ the version of Python to use. Should be in Major.Minor format, for
+ example, 2.3. Do not
+ include the subminor version (i.e. not
+ 2.5.1). If you have multiple Python versions
+ installed, the version will usually be the only configuration argument
+ required.
+
+
cmd-or-prefix
+
+ preferably, a command that invokes a Python interpreter. Alternatively,
+ the installation prefix for Python libraries and header files. Only
+ use the alternative formulation if there is no appropriate Python
+ executable available.
+
+
includes
+
+ the #include paths
+ for Python headers. Normally the correct path(s) will be automatically
+ deduced from version
+ and/or cmd-or-prefix.
+
+
libraries
+
+ the path to Python library binaries. On MacOS/Darwin, you can also
+ pass the path of the Python framework. Normally the correct path(s)
+ will be automatically deduced from version
+ and/or cmd-or-prefix.
+
+
condition
+
+ if specified, should be a set of Boost.Build properties that are
+ matched against the build configuration when Boost.Build selects
+ a Python configuration to use. See examples below for details.
+
+
extension-suffix
+
+ A string to append to the name of extension modules before the true
+ filename extension. You almost certainly don't need to use this.
+ Usually this suffix is only used when targeting a Windows debug build
+ of Python, and will be set automatically for you based on the value
+ of the <python-debugging>
+ feature. However, at least one Linux distribution (Ubuntu Feisty
+ Fawn) has a specially configured <python-dbg>
+ package that claims to use such a suffix.
+
+ You can set up your user-config.jam so a bjam built under Windows can
+ build/test both Windows and Cygwin_ python extensions. Just pass <target-os>cygwin
+ in the condition parameter
+ for the cygwin python installation:
+
+ when you put target-os=cygwin in your build request, it should build
+ with the cygwin version of python: _
+
+
bjamtarget-os=cygwintoolset=gcc
+
+
+ This is supposed to work the other way, too (targeting windows python
+ with a Cygwin bjam) but it seems
+ as though the support in Boost.Build's toolsets for building that way
+ is broken at the time of this writing.
+
+ 1. If you should ever have occasion to #include
+ "python.h" directly in a
+ translation unit of a program using Boost.Python, use #include
+ "boost/python/detail/wrap_python.hpp"
+ instead. It handles several issues necessary for use with Boost.Python, one
+ of which is mentioned in the next section.
+
+
+ 2. Be sure not to #include
+ any system headers before wrap_python.hpp. This
+ restriction is actually imposed by Python, or more properly, by Python's
+ interaction with your operating system. See http://docs.python.org/ext/simpleExample.html
+ for details.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/develop/html/building/installing_boost_python_on_your_.html b/doc/develop/html/building/installing_boost_python_on_your_.html
new file mode 100644
index 00000000..6ab4c4c3
--- /dev/null
+++ b/doc/develop/html/building/installing_boost_python_on_your_.html
@@ -0,0 +1,52 @@
+
+
+
+Installing Boost.Python on your System
+
+
+
+
+
+
+
+
+
+ Since Boost.Python is a separately-compiled (as opposed to header-only) library, its user relies on the services
+ of a Boost.Python library binary.
+
+
+ If you need a regular installation of the Boost.Python library binaries on
+ your system, the Boost Getting
+ Started Guide will walk you through the steps of creating one. If
+ building binaries from source, you might want to supply the --with-python
+ argument to bjam (or the
+ --with-libraries=python
+ argument to configure), so
+ only the Boost.Python binary will be built, rather than all the Boost binaries.
+
+ There is no need to “install Boost” in order to get started using Boost.Python.
+ These instructions use Boost.Build
+ projects, which will build those binaries as soon as they're needed. Your
+ first tests may take a little longer while you wait for Boost.Python to build,
+ but doing things this way will save you from worrying about build intricacies
+ like which library binaries to use for a specific compiler configuration
+ and figuring out the right compiler options to use yourself.
+
+
+
+
+
Note
+
+
+
+ Of course it's possible to use other build systems to build Boost.Python
+ and its extensions, but they are not officially supported by Boost. Moreover
+ 99% of all “I can't build Boost.Python” problems
+ come from trying to use another build system without first following
+ these instructions.
+
+
+ If you want to use another system anyway, we suggest that you follow these
+ instructions, and then invoke bjam
+ with the
+
+
+ -a
+ -ofilename
+
+
+ options to dump the build commands it executes to a file, so you can see
+ what your alternate build system needs to do.
+
+ 3. cd into the example/quickstart/ directory of your Boost.Python installation,
+ which contains a small example project.
+
+
+ 4. Invoke bjam. Replace
+ the “stage“ argument
+ from the example invocation from section 5 of the Boost Getting
+ Started Guide with “test,“
+ to build all the test targets. Also add the argument “--verbose-test” to see the output generated by
+ the tests when they are run. On Windows, your bjam
+ invocation might look something like:
+
+ For the sake of concision, the rest of this guide will use unix-style
+ forward slashes in pathnames instead of the backslashes with which Windows
+ users may be more familiar. The forward slashes should work everywhere
+ except in Command
+ Prompt windows, where you should use backslashes.
+
+
+
+ If you followed this procedure successfully, you will have built an extension
+ module called extending
+ and tested it by running a Python script called test_extending.py.
+ You will also have built and run a simple application called embedding that embeds python.
+
+ If you're seeing lots of compiler and/or linker error messages, it's probably
+ because Boost.Build is having trouble finding your Python installation.
+ You might want to pass the --debug-configuration option to bjam the first few times you invoke it,
+ to make sure that Boost.Build is correctly locating all the parts of your
+ Python installation. If it isn't, consider Configuring
+ Boost.Build as detailed below.
+
+
+ If you're still having trouble, Someone on one of the following mailing
+ lists may be able to help:
+
+ Rejoice! If you're new to Boost.Python, at this point it might be a good
+ idea to ignore build issues for a while and concentrate on learning the
+ library by going through the Tutorial
+ and perhaps some of the Reference Manual,
+ trying out what you've learned about the API by modifying the quickstart
+ project.
+
+ If you're content to keep your extension module forever in one source file
+ called extending.cpp, inside your Boost.Python distribution,
+ and import it forever as extending,
+ then you can stop here. However, it's likely that you will want to make
+ a few changes. There are a few things you can do without having to learn
+ Boost.Build in depth.
+
+
+ The project you just built is specified in two files in the current directory:
+ boost-build.jam, which tells bjam
+ where it can find the interpreted code of the Boost build system, and
+ Jamroot, which describes
+ the targets you just built. These files are heavily commented, so they
+ should be easy to modify. Take care, however, to preserve whitespace. Punctuation
+ such as ; will not be recognized
+ as intended by bjam if
+ it is not surrounded by whitespace.
+
+ You'll probably want to copy this project elsewhere so you can change
+ it without modifying your Boost distribution. To do that, simply
+
+
+ a. copy the entire example/quickstart/ directory into a new directory.
+
+
+ b. In the new copies of boost-build.jam
+ and Jamroot, locate the
+ relative path near the top of the file that is clearly marked by a comment,
+ and edit that path so that it refers to the same directory your Boost
+ distribution as it referred to when the file was in its original location
+ in the example/quickstart/
+ directory.
+
+
+ For example, if you moved the project from /home/dave/boost_1_34_0/libs/python/example/quickstart to /home/dave/my-project, you could change the first
+ path in boost-build.jam from
+
+ The names of additional source files involved in building your extension
+ module or embedding application can be listed in Jamroot
+ right alongside extending.cpp
+ or embedding.cpp respectively. Just be sure to leave
+ whitespace around each filename:
+
+
…file1.cppfile2.cppfile3.cpp…
+
+
+ Naturally, if you want to change the name of a source file you can tell
+ Boost.Build about it by editing the name in Jamroot.
+
+ If you are using a version of Python prior to 2.4.1 with a MinGW prior to
+ 3.0.0 (with binutils-2.13.90-20030111-1), you will need to create a MinGW-compatible
+ version of the Python library; the one shipped with Python will only work
+ with a Microsoft-compatible linker. Follow the instructions in the “Non-Microsoft”
+ section of the “Building Extensions: Tips And Tricks” chapter in Installing Python Modules
+ to create libpythonXX.a, where XX
+ corresponds to the major and minor version numbers of your Python installation.
+
+ Python can be built in a special “python debugging” configuration that
+ adds extra checks and instrumentation that can be very useful for developers
+ of extension modules. The data structures used by the debugging configuration
+ contain additional members, so a Python executable
+ built with python debugging enabled cannot be used with an extension module
+ or library compiled without it, and vice-versa.
+
+
+ Since pre-built “python debugging” versions of the Python executable
+ and libraries are not supplied with most distributions of Python, [5] and we didn't want to force our users to build them, Boost.Build
+ does not automatically enable python debugging in its debug
+ build variant (which is the default). Instead there is a special build property
+ called python-debugging that, when used as a build property,
+ will define the right preprocessor symbols and select the right libraries
+ to link with.
+
+
+ On unix-variant platforms, the debugging versions of Python's data structures
+ will only be used if the symbol Py_DEBUG
+ is defined. On many windows compilers, when extension modules are built with
+ the preprocessor symbol _DEBUG,
+ Python defaults to force linking with a special debugging version of the
+ Python DLL. Since that symbol is very commonly used even when Python is not
+ present, Boost.Python temporarily undefines _DEBUG
+ when Python.h is #included from boost/python/detail/wrap_python.hpp -
+ unless BOOST_DEBUG_PYTHON
+ is defined. The upshot is that if you want “python debugging”and you
+ aren't using Boost.Build, you should make sure BOOST_DEBUG_PYTHON
+ is defined, or python debugging will be suppressed.
+
+
+
+
[5]
+ On Unix and similar platforms, a debugging python and associated libraries
+ are built by adding --with-pydebug when configuring the Python build. On
+ Windows, the debugging version of Python is generated by the "Win32
+ Debug" target of the Visual Studio project in the PCBuild subdirectory
+ of a full Python source code distribution.
+
+ Boost.Python uses several configuration
+ macros in <boost/config.hpp>, as well as configuration macros meant
+ to be supplied by the application. These macros are documented here.
+
+ These are the macros that may be defined by an application using Boost.Python.
+ Note that if you extend a strict interpretation of the C++ standard to
+ cover dynamic libraries, using different values of these macros when compiling
+ different libraries (including extension modules and the Boost.Python library
+ itself) is a violation of the ODR. However,
+ we know of no C++ implementations on which this particular violation is
+ detectable or causes any problems.
+
+
+
+
+
+
+
+
+
+
+ Macro
+
+
+
+
+ Default
+
+
+
+
+ Meaning
+
+
+
+
+
+
+
+ BOOST_PYTHON_MAX_ARITY
+
+
+
+
+ 15
+
+
+
+
+ The maximum arity of any function, member function, or constructor
+ to be wrapped, invocation of a Boost.Python function wich is
+ specified as taking arguments x1, x2,...Xn. This includes, in
+ particular, callback mechanisms such as object::operator()(...)
+ or call_method<R>(... ).
+
+
+
+
+
+
+ BOOST_PYTHON_MAX_BASES
+
+
+
+
+ 10
+
+
+
+
+ The maximum number of template arguments to the bases<...>
+ class template, which is used to specify the bases of a wrapped
+ C++ class..
+
+
+
+
+
+
+ BOOST_PYTHON_STATIC_MODULE
+
+
+
+
+ not defined
+
+
+
+
+ If defined, prevents your module initialization function from
+ being treated as an exported symbol on platforms which support
+ that distinction in-code
+
+
+
+
+
+
+ BOOST_PYTHON_ENABLE_CDECL
+
+
+
+
+ not defined
+
+
+
+
+ If defined, allows functions using the __cdecl
+ calling convention to be wrapped.
+
+
+
+
+
+
+ BOOST_PYTHON_ENABLE_STDCALL
+
+
+
+
+ not defined
+
+
+
+
+ If defined, allows functions using the __stdcall
+ calling convention to be wrapped.
+
+
+
+
+
+
+ BOOST_PYTHON_ENABLE_FASTCALL
+
+
+
+
+ not defined
+
+
+
+
+ If defined, allows functions using the __fastcall
+ calling convention to be wrapped.
+
+ These macros are defined by Boost.Python
+ and are implementation details of interest only to implementors and those
+ porting to new platforms.
+
+
+
+
+
+
+
+
+
+
+ Macro
+
+
+
+
+ Default
+
+
+
+
+ Meaning
+
+
+
+
+
+
+
+ BOOST_PYTHON_TYPE_ID_NAME
+
+
+
+
+ not defined
+
+
+
+
+ If defined, this indicates that the type_info comparison across
+ shared library boundaries does not work on this platform. In
+ other words, if shared-lib-1 passes typeid(T) to a function in shared-lib-2
+ which compares it to typeid(T), that comparison may return
+ false. If this macro
+ is #defined, Boost.Python uses and compares typeid(T).name() instead of using and comparing
+ the std::type_info objects directly.
+
+
+
+
+
+
+ BOOST_PYTHON_NO_PY_SIGNATURES
+
+
+
+
+ not defined
+
+
+
+
+ If defined for a module no pythonic signatures are generated
+ for the docstrings of the module functions, and no python type
+ is associated with any of the converters registered by the module.
+ This also reduces the binary size of the module by about 14%
+ (gcc compiled). If defined for the boost_python runtime library,
+ the default for the docstring_options.enable_py_signatures() is set to false.
+
+
+
+
+
+
+ BOOST_PYTHON_SUPPORTS_PY_SIGNATURES
+
+
+
+
+ defined if BOOST_PYTHON_NO_PY_SIGNATURES
+ is undefined
+
+
+
+
+ This macro is defined to enable a smooth transition from older
+ Boost.Python versions which do not support pythonic signatures.
+ For example usage see here.
+
+ If defined the python type of __init__
+ method "self" parameters is properly generated, otherwise
+ object is used. It is undefined by default because it increases
+ the binary size of the module by about 14% (gcc compiled).
+
+ The short answer is: "you can't". This is not a Boost.Python limitation
+ so much as a limitation of C++. The problem is that a Python function is
+ actually data, and the only way of associating data with a C++ function pointer
+ is to store it in a static variable of the function. The problem with that
+ is that you can only associate one piece of data with every C++ function,
+ and we have no way of compiling a new C++ function on-the-fly for every Python
+ function you decide to pass to foo.
+ In other words, this could work if the C++ function is always going to invoke
+ the same Python function, but you probably don't want
+ that.
+
+
+ If you have the luxury of changing the C++ code you're wrapping, pass it
+ an object instead and call
+ that; the overloaded function call operator will invoke the Python function
+ you pass it behind the object.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/develop/html/faq/compilation_takes_too_much_time_.html b/doc/develop/html/faq/compilation_takes_too_much_time_.html
new file mode 100644
index 00000000..2fb2fcbe
--- /dev/null
+++ b/doc/develop/html/faq/compilation_takes_too_much_time_.html
@@ -0,0 +1,42 @@
+
+
+
+Compilation takes too much time and eats too much memory! What can I do to make it faster?
+
+
+
+
+
+
+
+
+
+ The last command requires root privileges because the target directory is
+ /Library/Frameworks/Python.framework/Versions/2.3. However,
+ the installation does not interfere with the Python version that ships with
+ 10.2.8.
+
+
+ It is also crucial to increase the stacksize
+ before starting compilations, e.g.:
+
+
limitstacksize8192k
+
+ If the stacksize is too small
+ the build might crash with internal compiler errors.
+
+
+ Sometimes Apple's compiler exhibits a bug by printing an error like the following
+ while compiling a boost::python::class_<your_type>
+ template instantiation:
+
+
.../inheritance.hpp:44:error:cannot
+ dynamic_cast`p' (of type `struct cctbx::boost_python::<unnamed>::add_pair*
+ ')totype`void*'(sourcetypeisnotpolymorphic)
+
+
+ We do not know a general workaround, but if the definition of your_type can be modified the following
+ was found to work in all cases encountered so far:
+
+
structyour_type
+{
+ // before defining any member data
+#ifdefined(__MACH__)&&defined(__APPLE_CC__)&&__APPLE_CC__==1493
+ booldummy_;
+#endif
+ // now your member data, e.g.
+ doublex;
+ intj;
+ // etc.
+};
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/develop/html/faq/error_c2064_term_does_not_evalua.html b/doc/develop/html/faq/error_c2064_term_does_not_evalua.html
new file mode 100644
index 00000000..c03ff124
--- /dev/null
+++ b/doc/develop/html/faq/error_c2064_term_does_not_evalua.html
@@ -0,0 +1,77 @@
+
+
+
+error C2064: term does not evaluate to a function taking 2 arguments
+
+
+
+
+
+
+
+
+
+ If you see Microsoft Visual C++ 7.1 (MS Visual Studio .NET 2003) issue an
+ error message like the following it is most likely due to a bug in the compiler:
+
+ If you find that a class_<...> declaration can't fit in a
+ single source file without triggering the error, you can always pass
+ a reference to the class_
+ object to a function in another source file, and call some of its member
+ functions (e.g. .def(...)) in the auxilliary source file:
+
+
+
diff --git a/doc/develop/html/faq/how_can_i_automatically_convert_.html b/doc/develop/html/faq/how_can_i_automatically_convert_.html
new file mode 100644
index 00000000..cc186764
--- /dev/null
+++ b/doc/develop/html/faq/how_can_i_automatically_convert_.html
@@ -0,0 +1,146 @@
+
+
+
+How can I automatically convert my custom string type to and from a Python string?
+
+
+
+
+
+
+
+
+
+ A custom to_python converter
+ (easy): custom_string_to_python_str
+
+
+ A custom lvalue converter (needs more code): custom_string_from_python_str
+
+
+
+ The custom converters are registered in the global Boost.Python registry
+ near the top of the module initialization function. Once flow control has
+ passed through the registration code the automatic conversions from and to
+ Python strings will work in any module imported in the same process.
+
+ "I am wrapping a function that always returns a pointer to an already-held
+ C++ object."
+
+
+ One way to do that is to hijack the mechanisms used for wrapping a class
+ with virtual functions. If you make a wrapper class with an initial PyObject*
+ constructor argument and store that PyObject* as "self", you can
+ get back to it by casting down to that wrapper type in a thin wrapper function.
+ For example:
+
+
classX{X(int);virtual~X();...};
+X*f();// known to return Xs that are managed by Python objects
+
+
+// wrapping code
+
+structX_wrap:X
+{
+ X_wrap(PyObject*self,intv):self(self),X(v){}
+ PyObject*self;
+};
+
+handle<>f_wrap()
+{
+ X_wrap*xw=dynamic_cast<X_wrap*>(f());
+ assert(xw!=0);
+ returnhandle<>(borrowed(xw->self));
+}
+
+...
+
+def("f",f_wrap());
+class_<X,X_wrap,boost::noncopyable>("X",init<int>())
+ ...
+ ;
+
+
+ Of course, if X has no virtual functions you'll have to use static_cast instead of dynamic_cast
+ with no runtime check that it's valid. This approach also only works if the
+ X object was constructed
+ from Python, because Xs constructed
+ from C++ are of course never X_wrap
+ objects.
+
+
+ Another approach to this requires you to change your C++ code a bit; if that's
+ an option for you it might be a better way to go. work we've been meaning
+ to get to anyway. When a shared_ptr<X>
+ is converted from Python, the shared_ptr actually manages a reference to
+ the containing Python object. When a shared_ptr<X> is converted back
+ to Python, the library checks to see if it's one of those "Python object
+ managers" and if so just returns the original Python object. So you
+ could just write object(p) to get
+ the Python object back. To exploit this you'd have to be able to change the
+ C++ code you're wrapping so that it deals with shared_ptr instead of raw
+ pointers.
+
+
+ There are other approaches too. The functions that receive the Python object
+ that you eventually want to return could be wrapped with a thin wrapper that
+ records the correspondence between the object address and its containing
+ Python object, and you could have your f_wrap function look in that mapping
+ to get the Python object out.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/develop/html/faq/how_can_i_wrap_a_function_which0.html b/doc/develop/html/faq/how_can_i_wrap_a_function_which0.html
new file mode 100644
index 00000000..b107a256
--- /dev/null
+++ b/doc/develop/html/faq/how_can_i_wrap_a_function_which0.html
@@ -0,0 +1,86 @@
+
+
+
+How can I wrap a function which needs to take ownership of a raw pointer?
+
+
+
+
+
+
+
+
+
+ Even binding the lifetime of a to b via with_custodian_and_ward
+ doesn't prevent the python object a from ultimately trying to delete the
+ object it's pointing to. Is there a way to accomplish a 'transfer-of-ownership'
+ of a wrapped C++ object?
+
+
+ --Bruce Lowery
+
+
+ Yes: Make sure the C++ object is held by auto_ptr:
+
+
class_<A,std::auto_ptr<A>>("A")
+ ...
+ ;
+
+
+ Then make a thin wrapper function which takes an auto_ptr parameter:
+
+ Wrap that as B.add. Note that pointers returned via manage_new_object
+ will also be held by auto_ptr,
+ so this transfer-of-ownership will also work correctly.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/develop/html/faq/how_can_i_wrap_functions_which_t.html b/doc/develop/html/faq/how_can_i_wrap_functions_which_t.html
new file mode 100644
index 00000000..ba8e1b97
--- /dev/null
+++ b/doc/develop/html/faq/how_can_i_wrap_functions_which_t.html
@@ -0,0 +1,124 @@
+
+
+
+How can I wrap functions which take C++ containers as arguments?
+
+
+
+
+
+
+
+
+
+ This can be moved to a template so that several types (double, int,
+ long, etc.) can be wrapped
+ with the same code. This technique is used in the file scitbx/include/scitbx/array_family/boost_python/flex_wrapper.h in the "scitbx" package.
+ The file could easily be modified for wrapping std::vector<> instantiations. This type of
+ C++/Python binding is most suitable for containers that may contain a
+ large number of elements (>10000).
+
+
+
+
+ Using custom rvalue converters. Boost.Python "rvalue converters"
+ match function signatures such as:
+
+
voidfoo(std::vector<double>const&array);// pass by const-reference
+voidfoo(std::vector<double>array);// pass by value
+
+
+ Some custom rvalue converters are implemented in the file scitbx/include/scitbx/boost_python/container_conversions.h This code can be used to convert
+ from C++ container types such as std::vector<> or std::list<> to Python tuples and vice versa.
+ A few simple examples can be found in the file scitbx/array_family/boost_python/regression_test_module.cpp
+ Automatic C++ container <-> Python tuple conversions are most suitable
+ for containers of moderate size. These converters generate significantly
+ less object code compared to alternative 1 above.
+
+
+
+
+ A disadvantage of using alternative 2 is that operators such as arithmetic
+ +,-,*,/,% are not available. It would be useful to have custom rvalue converters
+ that convert to a "math_array" type instead of tuples. This is
+ currently not implemented but is possible within the framework of Boost.Python
+ V2 as it will be released in the next couple of weeks. [ed.: this was posted
+ on 2002/03/10]
+
+
+ It would also be useful to also have "custom lvalue converters"
+ such as std::vector<>
+ <-> Python list. These converters would support the modification of
+ the Python list from C++. For example:
+
+ Greg Burley gives the following answer for Unix GCC users:
+
+
+
+ Once you have created a boost python extension for your c++ library or
+ class, you may need to debug the code. Afterall this is one of the reasons
+ for wrapping the library in python. An expected side-effect or benefit
+ of using BPL is that debugging should be isolated to the c++ library that
+ is under test, given that python code is minimal and boost::python either
+ works or it doesn't. (ie. While errors can occur when the wrapping method
+ is invalid, most errors are caught by the compiler ;-).
+
+
+ The basic steps required to initiate a gdb session to debug a c++ library
+ via python are shown here. Note, however that you should start the gdb
+ session in the directory that contains your BPL my_ext.so module.
+
+ Greg's approach works even better using Emacs' "gdb" command, since
+ it will show you each line of source as you step through it.
+
+
+ On Windows, my favorite debugging solution
+ is the debugger that comes with Microsoft Visual C++ 7. This debugger seems
+ to work with code generated by all versions of Microsoft and Metrowerks toolsets;
+ it's rock solid and "just works" without requiring any special
+ tricks from the user.
+
+
+ Raoul Gough has provided the following for gdb on Windows:
+
+
+
+ gdb support for Windows DLLs has improved lately, so it is now possible
+ to debug Python extensions using a few tricks. Firstly, you will need an
+ up-to-date gdb with support for minimal symbol extraction from a DLL. Any
+ gdb from version 6 onwards, or Cygwin gdb-20030214-1 and onwards should
+ do. A suitable release will have a section in the gdb.info file under Configuration
+ - Native - Cygwin Native - Non-debug DLL symbols. Refer to that info section
+ for more details of the procedures outlined here.
+
+
+ Secondly, it seems necessary to set a breakpoint in the Python interpreter,
+ rather than using ^C to break execution. A good place to set this breakpoint
+ is PyOS_Readline, which will stop execution immediately before reading
+ each interactive Python command. You have to let Python start once under
+ the debugger, so that it loads its own DLL, before you can set the breakpoint:
+
+ If you are launching your extension module tests with Boost.Build
+ using the boost-python-runtest rule, you can ask it to launch
+ your debugger for you by adding "--debugger=debugger"
+ to your bjam command-line:
+
+ It can also be extremely useful to add the -d+2
+ option when you run your test, because Boost.Build will then show you the
+ exact commands it uses to invoke it. This will invariably involve setting
+ up PYTHONPATH and other important environment variables such as LD_LIBRARY_PATH
+ which may be needed by your debugger in order to get things to work right.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/develop/html/faq/i_m_getting_the_attempt_to_retur.html b/doc/develop/html/faq/i_m_getting_the_attempt_to_retur.html
new file mode 100644
index 00000000..7d1f857a
--- /dev/null
+++ b/doc/develop/html/faq/i_m_getting_the_attempt_to_retur.html
@@ -0,0 +1,67 @@
+
+
+
+I'm getting the "attempt to return dangling reference" error. What am I doing wrong?
+
+
+
+
+
+
+
+
+
+ In this case, the Python method invoked by call_method
+ constructs a new Python object. You're trying to return a reference to a
+ C++ object (an instance of classperiod) contained within and owned by that
+ Python object. Because the called method handed back a brand new object,
+ the only reference to it is held for the duration of get_floating_frequency() above. When the function returns, the Python
+ object will be destroyed, destroying the instance of class
+ period, and leaving the returned
+ reference dangling. That's already undefined behavior, and if you try to
+ do anything with that reference you're likely to cause a crash. Boost.Python
+ detects this situation at runtime and helpfully throws an exception instead
+ of letting you do that.
+
+ The longer answer is that it can be patched to be so, but it's complex. You
+ will need to add custom lock/unlock wrapping of every time your code enters
+ Boost.Python (particularly every virtual function override) plus heavily
+ modify boost/python/detail/invoke.hpp with custom unlock/lock wrapping of
+ every time Boost.Python enters your code. You must furthermore take care
+ to not unlock/lock when Boost.Python is invoking iterator
+ changes via invoke.hpp.
+
+
+ There is a patched invoke.hpp posted
+ on the C++-SIG mailing list archives and you can find a real implementation
+ of all the machinery necessary to fully implement this in the TnFOX project
+ at this SourceForge
+ project location.
+
+ Q: /I have an object composed of 12 doubles.
+ A const&
+ to this object is returned by a member function of another class. From the
+ viewpoint of using the returned object in Python I do not care if I get a
+ copy or a reference to the returned object. In Boost.Python I have the choice
+ of using copy_const_reference
+ or return_internal_reference.
+ Are there considerations that would lead me to prefer one over the other,
+ such as size of generated code or memory overhead?/
+
+
+ A:copy_const_reference
+ will make an instance with storage for one of your objects, size=base_size+12*sizeof(double).
+ return_internal_reference
+ will make an instance with storage for a pointer to one of your objects,
+ size=
+ base_size+
+ sizeof(void*). However,
+ it will also create a weak reference object which goes in the source object's
+ weakreflist and a special callback object to manage the lifetime of the internally-referenced
+ object. My guess? copy_const_reference
+ is your friend here, resulting in less overall memory use and less fragmentation,
+ also probably fewer total cycles.
+
+ Q:I have exported my class to
+ python, with many overloaded operators. it works fine for me except the
+ *= operator. It always tells
+ me "can't multiply sequence with non int type". If I use p1.__imul__(p2)
+ instead of p1*=
+ p2, it successfully executes my
+ code. What's wrong with me?
+
+
+ A: There's nothing wrong with you. This
+ is a bug in Python 2.2. You can see the same effect in Pure Python (you can
+ learn a lot about what's happening in Boost.Python by playing with new-style
+ classes in Pure Python).
+
+ If you define custom converters similar to the ones shown above the def_readonly()
+ and def_readwrite()
+ member functions provided by boost::python::class_
+ for direct access to your member data will not work as expected. This is
+ because def_readonly("bar",&foo::bar) is equivalent to:
+
+ In order to define return value policies compatible with the custom conversions
+ replace def_readonly()
+ and def_readwrite()
+ by add_property().
+ E.g.:
+
+ The number of argumnts accepted by a function or member function. Unless
+ otherwise specified, the hidden this
+ argument to member functions is not counted when specifying arity.
+
+
ntbs
+
+ Null-Terminated Byte String, or 'C'-string. C++ string literals are
+ ntbses. An ntbs
+ must never be null.
+
+
raise
+
+ Exceptions in Python are "raised", not "thrown",
+ as they are in C++. When this documentation says that some Python exception
+ is "raised" in the context of C++ code, it means that the corresponding
+ Python exception is set via the Python/'C'
+ API, and throw_error_already_set() is called.
+
+
POD
+
+ A technical term from the C++ standard. Short for "Plain Ol'Data":
+ A POD-struct is an aggregate class that has no non-static data members
+ of type pointer to member, non-POD-struct, non-POD-union (or array of
+ such types) or reference, and has no user-defined copy assign- ment operator
+ and no user-defined destructor. Similarly, a POD-union is an aggregate
+ union that has no non-static data members of type pointer to member,
+ non-POD-struct, non-POD-union (or array of such types) or reference,
+ and has no user-defined copy assignment operator and no user-defined
+ destructor. A POD class is a class that is either a POD-struct or a POD-union.
+ An aggregate is an array or a class (clause 9) with no user-declared
+ constructors (12.1), no private or protected non-static data members
+ (clause 11), no base classes (clause 10), and no virtual functions (10.3).
+
+
ODR
+
+ The "One Definition Rule", which says that any entity in a
+ C++ program must have the same definition in all translation units (object
+ files) which make up a program.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/develop/html/images/alert.png b/doc/develop/html/images/alert.png
new file mode 100644
index 00000000..b4645bc7
Binary files /dev/null and b/doc/develop/html/images/alert.png differ
diff --git a/doc/develop/html/images/blank.png b/doc/develop/html/images/blank.png
new file mode 100644
index 00000000..764bf4f0
Binary files /dev/null and b/doc/develop/html/images/blank.png differ
diff --git a/doc/develop/html/images/boost.png b/doc/develop/html/images/boost.png
new file mode 100644
index 00000000..b4d51fcd
Binary files /dev/null and b/doc/develop/html/images/boost.png differ
diff --git a/doc/develop/html/images/bpl.png b/doc/develop/html/images/bpl.png
new file mode 100644
index 00000000..c2d8c69e
Binary files /dev/null and b/doc/develop/html/images/bpl.png differ
diff --git a/doc/develop/html/images/bpl.svg b/doc/develop/html/images/bpl.svg
new file mode 100644
index 00000000..9a72d2c4
--- /dev/null
+++ b/doc/develop/html/images/bpl.svg
@@ -0,0 +1,224 @@
+
+
\ No newline at end of file
diff --git a/doc/develop/html/images/callouts/1.png b/doc/develop/html/images/callouts/1.png
new file mode 100644
index 00000000..6003ad3a
Binary files /dev/null and b/doc/develop/html/images/callouts/1.png differ
diff --git a/doc/develop/html/images/callouts/1.svg b/doc/develop/html/images/callouts/1.svg
new file mode 100644
index 00000000..e2e87dc5
--- /dev/null
+++ b/doc/develop/html/images/callouts/1.svg
@@ -0,0 +1,15 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/10.png b/doc/develop/html/images/callouts/10.png
new file mode 100644
index 00000000..0426f516
Binary files /dev/null and b/doc/develop/html/images/callouts/10.png differ
diff --git a/doc/develop/html/images/callouts/10.svg b/doc/develop/html/images/callouts/10.svg
new file mode 100644
index 00000000..4740f587
--- /dev/null
+++ b/doc/develop/html/images/callouts/10.svg
@@ -0,0 +1,18 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/11.png b/doc/develop/html/images/callouts/11.png
new file mode 100644
index 00000000..821afc4f
Binary files /dev/null and b/doc/develop/html/images/callouts/11.png differ
diff --git a/doc/develop/html/images/callouts/11.svg b/doc/develop/html/images/callouts/11.svg
new file mode 100644
index 00000000..09a0b2cf
--- /dev/null
+++ b/doc/develop/html/images/callouts/11.svg
@@ -0,0 +1,16 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/12.png b/doc/develop/html/images/callouts/12.png
new file mode 100644
index 00000000..7cec7272
Binary files /dev/null and b/doc/develop/html/images/callouts/12.png differ
diff --git a/doc/develop/html/images/callouts/12.svg b/doc/develop/html/images/callouts/12.svg
new file mode 100644
index 00000000..9794044c
--- /dev/null
+++ b/doc/develop/html/images/callouts/12.svg
@@ -0,0 +1,18 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/13.png b/doc/develop/html/images/callouts/13.png
new file mode 100644
index 00000000..5b41e02a
Binary files /dev/null and b/doc/develop/html/images/callouts/13.png differ
diff --git a/doc/develop/html/images/callouts/13.svg b/doc/develop/html/images/callouts/13.svg
new file mode 100644
index 00000000..64268bb4
--- /dev/null
+++ b/doc/develop/html/images/callouts/13.svg
@@ -0,0 +1,20 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/14.png b/doc/develop/html/images/callouts/14.png
new file mode 100644
index 00000000..de5bdbd3
Binary files /dev/null and b/doc/develop/html/images/callouts/14.png differ
diff --git a/doc/develop/html/images/callouts/14.svg b/doc/develop/html/images/callouts/14.svg
new file mode 100644
index 00000000..469aa974
--- /dev/null
+++ b/doc/develop/html/images/callouts/14.svg
@@ -0,0 +1,17 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/15.png b/doc/develop/html/images/callouts/15.png
new file mode 100644
index 00000000..3fd6ac38
Binary files /dev/null and b/doc/develop/html/images/callouts/15.png differ
diff --git a/doc/develop/html/images/callouts/15.svg b/doc/develop/html/images/callouts/15.svg
new file mode 100644
index 00000000..8202233e
--- /dev/null
+++ b/doc/develop/html/images/callouts/15.svg
@@ -0,0 +1,19 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/16.svg b/doc/develop/html/images/callouts/16.svg
new file mode 100644
index 00000000..01d6bf81
--- /dev/null
+++ b/doc/develop/html/images/callouts/16.svg
@@ -0,0 +1,20 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/17.svg b/doc/develop/html/images/callouts/17.svg
new file mode 100644
index 00000000..0a04c556
--- /dev/null
+++ b/doc/develop/html/images/callouts/17.svg
@@ -0,0 +1,17 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/18.svg b/doc/develop/html/images/callouts/18.svg
new file mode 100644
index 00000000..1cb891b3
--- /dev/null
+++ b/doc/develop/html/images/callouts/18.svg
@@ -0,0 +1,21 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/19.svg b/doc/develop/html/images/callouts/19.svg
new file mode 100644
index 00000000..e6fbb179
--- /dev/null
+++ b/doc/develop/html/images/callouts/19.svg
@@ -0,0 +1,20 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/2.png b/doc/develop/html/images/callouts/2.png
new file mode 100644
index 00000000..f7c15788
Binary files /dev/null and b/doc/develop/html/images/callouts/2.png differ
diff --git a/doc/develop/html/images/callouts/2.svg b/doc/develop/html/images/callouts/2.svg
new file mode 100644
index 00000000..07d03395
--- /dev/null
+++ b/doc/develop/html/images/callouts/2.svg
@@ -0,0 +1,17 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/20.svg b/doc/develop/html/images/callouts/20.svg
new file mode 100644
index 00000000..ccbfd403
--- /dev/null
+++ b/doc/develop/html/images/callouts/20.svg
@@ -0,0 +1,20 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/21.svg b/doc/develop/html/images/callouts/21.svg
new file mode 100644
index 00000000..93ec53fd
--- /dev/null
+++ b/doc/develop/html/images/callouts/21.svg
@@ -0,0 +1,18 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/22.svg b/doc/develop/html/images/callouts/22.svg
new file mode 100644
index 00000000..f48c5f3f
--- /dev/null
+++ b/doc/develop/html/images/callouts/22.svg
@@ -0,0 +1,20 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/23.svg b/doc/develop/html/images/callouts/23.svg
new file mode 100644
index 00000000..66242129
--- /dev/null
+++ b/doc/develop/html/images/callouts/23.svg
@@ -0,0 +1,22 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/24.svg b/doc/develop/html/images/callouts/24.svg
new file mode 100644
index 00000000..a3d55253
--- /dev/null
+++ b/doc/develop/html/images/callouts/24.svg
@@ -0,0 +1,19 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/25.svg b/doc/develop/html/images/callouts/25.svg
new file mode 100644
index 00000000..56614a97
--- /dev/null
+++ b/doc/develop/html/images/callouts/25.svg
@@ -0,0 +1,21 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/26.svg b/doc/develop/html/images/callouts/26.svg
new file mode 100644
index 00000000..56faeaca
--- /dev/null
+++ b/doc/develop/html/images/callouts/26.svg
@@ -0,0 +1,22 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/27.svg b/doc/develop/html/images/callouts/27.svg
new file mode 100644
index 00000000..a75c8121
--- /dev/null
+++ b/doc/develop/html/images/callouts/27.svg
@@ -0,0 +1,19 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/28.svg b/doc/develop/html/images/callouts/28.svg
new file mode 100644
index 00000000..7f8cf1a3
--- /dev/null
+++ b/doc/develop/html/images/callouts/28.svg
@@ -0,0 +1,23 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/29.svg b/doc/develop/html/images/callouts/29.svg
new file mode 100644
index 00000000..cb63adf1
--- /dev/null
+++ b/doc/develop/html/images/callouts/29.svg
@@ -0,0 +1,22 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/3.png b/doc/develop/html/images/callouts/3.png
new file mode 100644
index 00000000..3ff0a939
Binary files /dev/null and b/doc/develop/html/images/callouts/3.png differ
diff --git a/doc/develop/html/images/callouts/3.svg b/doc/develop/html/images/callouts/3.svg
new file mode 100644
index 00000000..918be806
--- /dev/null
+++ b/doc/develop/html/images/callouts/3.svg
@@ -0,0 +1,19 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/30.svg b/doc/develop/html/images/callouts/30.svg
new file mode 100644
index 00000000..dc43ba1e
--- /dev/null
+++ b/doc/develop/html/images/callouts/30.svg
@@ -0,0 +1,22 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/4.png b/doc/develop/html/images/callouts/4.png
new file mode 100644
index 00000000..6aa29fc0
Binary files /dev/null and b/doc/develop/html/images/callouts/4.png differ
diff --git a/doc/develop/html/images/callouts/4.svg b/doc/develop/html/images/callouts/4.svg
new file mode 100644
index 00000000..8eb6a53b
--- /dev/null
+++ b/doc/develop/html/images/callouts/4.svg
@@ -0,0 +1,16 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/5.png b/doc/develop/html/images/callouts/5.png
new file mode 100644
index 00000000..36e78586
Binary files /dev/null and b/doc/develop/html/images/callouts/5.png differ
diff --git a/doc/develop/html/images/callouts/5.svg b/doc/develop/html/images/callouts/5.svg
new file mode 100644
index 00000000..ca7a9f22
--- /dev/null
+++ b/doc/develop/html/images/callouts/5.svg
@@ -0,0 +1,18 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/6.png b/doc/develop/html/images/callouts/6.png
new file mode 100644
index 00000000..c943676b
Binary files /dev/null and b/doc/develop/html/images/callouts/6.png differ
diff --git a/doc/develop/html/images/callouts/6.svg b/doc/develop/html/images/callouts/6.svg
new file mode 100644
index 00000000..783a0b9d
--- /dev/null
+++ b/doc/develop/html/images/callouts/6.svg
@@ -0,0 +1,19 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/7.png b/doc/develop/html/images/callouts/7.png
new file mode 100644
index 00000000..20940de3
Binary files /dev/null and b/doc/develop/html/images/callouts/7.png differ
diff --git a/doc/develop/html/images/callouts/7.svg b/doc/develop/html/images/callouts/7.svg
new file mode 100644
index 00000000..59b3714b
--- /dev/null
+++ b/doc/develop/html/images/callouts/7.svg
@@ -0,0 +1,16 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/8.png b/doc/develop/html/images/callouts/8.png
new file mode 100644
index 00000000..d8e34d4a
Binary files /dev/null and b/doc/develop/html/images/callouts/8.png differ
diff --git a/doc/develop/html/images/callouts/8.svg b/doc/develop/html/images/callouts/8.svg
new file mode 100644
index 00000000..c1803a3c
--- /dev/null
+++ b/doc/develop/html/images/callouts/8.svg
@@ -0,0 +1,20 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/callouts/9.png b/doc/develop/html/images/callouts/9.png
new file mode 100644
index 00000000..abe63607
Binary files /dev/null and b/doc/develop/html/images/callouts/9.png differ
diff --git a/doc/develop/html/images/callouts/9.svg b/doc/develop/html/images/callouts/9.svg
new file mode 100644
index 00000000..bc149d3c
--- /dev/null
+++ b/doc/develop/html/images/callouts/9.svg
@@ -0,0 +1,19 @@
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/caution.png b/doc/develop/html/images/caution.png
new file mode 100644
index 00000000..5b7809ca
Binary files /dev/null and b/doc/develop/html/images/caution.png differ
diff --git a/doc/develop/html/images/caution.svg b/doc/develop/html/images/caution.svg
new file mode 100644
index 00000000..4bd586a0
--- /dev/null
+++ b/doc/develop/html/images/caution.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/doc/develop/html/images/draft.png b/doc/develop/html/images/draft.png
new file mode 100644
index 00000000..0084708c
Binary files /dev/null and b/doc/develop/html/images/draft.png differ
diff --git a/doc/develop/html/images/home.png b/doc/develop/html/images/home.png
new file mode 100644
index 00000000..5584aacb
Binary files /dev/null and b/doc/develop/html/images/home.png differ
diff --git a/doc/develop/html/images/home.svg b/doc/develop/html/images/home.svg
new file mode 100644
index 00000000..e803a317
--- /dev/null
+++ b/doc/develop/html/images/home.svg
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/important.png b/doc/develop/html/images/important.png
new file mode 100644
index 00000000..12c90f60
Binary files /dev/null and b/doc/develop/html/images/important.png differ
diff --git a/doc/develop/html/images/important.svg b/doc/develop/html/images/important.svg
new file mode 100644
index 00000000..dd84f3fe
--- /dev/null
+++ b/doc/develop/html/images/important.svg
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/jam.png b/doc/develop/html/images/jam.png
new file mode 100644
index 00000000..224ed791
Binary files /dev/null and b/doc/develop/html/images/jam.png differ
diff --git a/doc/develop/html/images/next.png b/doc/develop/html/images/next.png
new file mode 100644
index 00000000..59800b4e
Binary files /dev/null and b/doc/develop/html/images/next.png differ
diff --git a/doc/develop/html/images/next.svg b/doc/develop/html/images/next.svg
new file mode 100644
index 00000000..75fa83ed
--- /dev/null
+++ b/doc/develop/html/images/next.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/next_disabled.png b/doc/develop/html/images/next_disabled.png
new file mode 100644
index 00000000..10a8c59d
Binary files /dev/null and b/doc/develop/html/images/next_disabled.png differ
diff --git a/doc/develop/html/images/note.png b/doc/develop/html/images/note.png
new file mode 100644
index 00000000..d0c3c645
Binary files /dev/null and b/doc/develop/html/images/note.png differ
diff --git a/doc/develop/html/images/note.svg b/doc/develop/html/images/note.svg
new file mode 100644
index 00000000..648299d2
--- /dev/null
+++ b/doc/develop/html/images/note.svg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/prev.png b/doc/develop/html/images/prev.png
new file mode 100644
index 00000000..d88a40f9
Binary files /dev/null and b/doc/develop/html/images/prev.png differ
diff --git a/doc/develop/html/images/prev.svg b/doc/develop/html/images/prev.svg
new file mode 100644
index 00000000..6d88ffdd
--- /dev/null
+++ b/doc/develop/html/images/prev.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/prev_disabled.png b/doc/develop/html/images/prev_disabled.png
new file mode 100644
index 00000000..ab3c17e0
Binary files /dev/null and b/doc/develop/html/images/prev_disabled.png differ
diff --git a/doc/develop/html/images/smiley.png b/doc/develop/html/images/smiley.png
new file mode 100644
index 00000000..30a77f71
Binary files /dev/null and b/doc/develop/html/images/smiley.png differ
diff --git a/doc/develop/html/images/tip.png b/doc/develop/html/images/tip.png
new file mode 100644
index 00000000..5c4aab3b
Binary files /dev/null and b/doc/develop/html/images/tip.png differ
diff --git a/doc/develop/html/images/tip.svg b/doc/develop/html/images/tip.svg
new file mode 100644
index 00000000..cd437a5e
--- /dev/null
+++ b/doc/develop/html/images/tip.svg
@@ -0,0 +1,84 @@
+
+
diff --git a/doc/develop/html/images/toc-blank.png b/doc/develop/html/images/toc-blank.png
new file mode 100644
index 00000000..6ffad17a
Binary files /dev/null and b/doc/develop/html/images/toc-blank.png differ
diff --git a/doc/develop/html/images/toc-minus.png b/doc/develop/html/images/toc-minus.png
new file mode 100644
index 00000000..abbb020c
Binary files /dev/null and b/doc/develop/html/images/toc-minus.png differ
diff --git a/doc/develop/html/images/toc-plus.png b/doc/develop/html/images/toc-plus.png
new file mode 100644
index 00000000..941312ce
Binary files /dev/null and b/doc/develop/html/images/toc-plus.png differ
diff --git a/doc/develop/html/images/up.png b/doc/develop/html/images/up.png
new file mode 100644
index 00000000..17d9c3ec
Binary files /dev/null and b/doc/develop/html/images/up.png differ
diff --git a/doc/develop/html/images/up.svg b/doc/develop/html/images/up.svg
new file mode 100644
index 00000000..d31aa9c8
--- /dev/null
+++ b/doc/develop/html/images/up.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+]>
+
diff --git a/doc/develop/html/images/up_disabled.png b/doc/develop/html/images/up_disabled.png
new file mode 100644
index 00000000..e22bc871
Binary files /dev/null and b/doc/develop/html/images/up_disabled.png differ
diff --git a/doc/develop/html/images/warning.png b/doc/develop/html/images/warning.png
new file mode 100644
index 00000000..1c33db8f
Binary files /dev/null and b/doc/develop/html/images/warning.png differ
diff --git a/doc/develop/html/images/warning.svg b/doc/develop/html/images/warning.svg
new file mode 100644
index 00000000..fc8d7484
--- /dev/null
+++ b/doc/develop/html/images/warning.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+]>
+
diff --git a/doc/develop/html/index.html b/doc/develop/html/index.html
new file mode 100644
index 00000000..31168cdc
--- /dev/null
+++ b/doc/develop/html/index.html
@@ -0,0 +1,135 @@
+
+
+
+Boost.Python
+
+
+
+
+
+
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+ Welcome to Boost.Python, a C++ library which enables seamless interoperability
+ between C++ and the Python programming language. The library includes support
+ for:
+