From 1a78a62555be32868418fe52f8e330c9d0f95d5a Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Tue, 30 Oct 2012 12:57:26 -0700 Subject: Imported Upstream version 1.49.0 --- libs/python/doc/Jamfile | 23 + libs/python/doc/PyConDC_2003/bpl.html | 22 + libs/python/doc/PyConDC_2003/bpl.pdf | Bin 0 -> 7316 bytes libs/python/doc/PyConDC_2003/bpl.txt | 5 + libs/python/doc/PyConDC_2003/bpl_mods.txt | 911 +++++++++ libs/python/doc/PyConDC_2003/default.css | 188 ++ libs/python/doc/PyConDC_2003/python_cpp_mix.jpg | Bin 0 -> 22831 bytes libs/python/doc/PyConDC_2003/python_cpp_mix.png | Bin 0 -> 6293 bytes libs/python/doc/boost.css | 63 + libs/python/doc/building.html | 636 +++++++ libs/python/doc/building.rst | 680 +++++++ libs/python/doc/index.html | 184 ++ libs/python/doc/internals.html | 186 ++ libs/python/doc/internals.rst | 182 ++ libs/python/doc/news.html | 371 ++++ libs/python/doc/polymorphism.txt | 222 +++ libs/python/doc/projects.html | 466 +++++ libs/python/doc/support.html | 74 + libs/python/doc/tutorial/doc/Jamfile.v2 | 18 + libs/python/doc/tutorial/doc/html/images/alert.png | Bin 0 -> 603 bytes libs/python/doc/tutorial/doc/html/images/home.png | Bin 0 -> 358 bytes libs/python/doc/tutorial/doc/html/images/jam.png | Bin 0 -> 3884 bytes libs/python/doc/tutorial/doc/html/images/next.png | Bin 0 -> 336 bytes libs/python/doc/tutorial/doc/html/images/note.png | Bin 0 -> 658 bytes libs/python/doc/tutorial/doc/html/images/prev.png | Bin 0 -> 334 bytes .../python/doc/tutorial/doc/html/images/python.png | Bin 0 -> 14699 bytes .../python/doc/tutorial/doc/html/images/smiley.png | Bin 0 -> 867 bytes libs/python/doc/tutorial/doc/html/images/tip.png | Bin 0 -> 640 bytes libs/python/doc/tutorial/doc/html/images/up.png | Bin 0 -> 370 bytes libs/python/doc/tutorial/doc/html/index.html | 142 ++ .../doc/tutorial/doc/html/python/embedding.html | 269 +++ .../doc/tutorial/doc/html/python/exception.html | 63 + .../doc/tutorial/doc/html/python/exposing.html | 591 ++++++ .../doc/tutorial/doc/html/python/functions.html | 586 ++++++ .../python/doc/tutorial/doc/html/python/hello.html | 195 ++ .../doc/tutorial/doc/html/python/iterators.html | 187 ++ .../doc/tutorial/doc/html/python/object.html | 360 ++++ .../doc/tutorial/doc/html/python/techniques.html | 440 +++++ libs/python/doc/tutorial/doc/tutorial.qbk | 1985 ++++++++++++++++++++ libs/python/doc/tutorial/index.html | 18 + libs/python/doc/v2/Apr2002.html | 166 ++ libs/python/doc/v2/CallPolicies.html | 165 ++ libs/python/doc/v2/Dereferenceable.html | 74 + libs/python/doc/v2/Extractor.html | 96 + libs/python/doc/v2/HolderGenerator.html | 74 + libs/python/doc/v2/Jun2002.html | 229 +++ libs/python/doc/v2/Mar2002.html | 237 +++ libs/python/doc/v2/May2002.html | 311 +++ libs/python/doc/v2/ObjectWrapper.html | 153 ++ libs/python/doc/v2/ResultConverter.html | 124 ++ libs/python/doc/v2/acknowledgments.html | 135 ++ libs/python/doc/v2/args.html | 199 ++ libs/python/doc/v2/call.html | 85 + libs/python/doc/v2/call_method.html | 161 ++ libs/python/doc/v2/callbacks.html | 254 +++ libs/python/doc/v2/callbacks.txt | 92 + libs/python/doc/v2/class.html | 790 ++++++++ libs/python/doc/v2/configuration.html | 217 +++ libs/python/doc/v2/copy_const_reference.html | 149 ++ libs/python/doc/v2/copy_non_const_reference.html | 149 ++ libs/python/doc/v2/data_members.html | 229 +++ libs/python/doc/v2/def.html | 191 ++ libs/python/doc/v2/def_visitor.html | 137 ++ libs/python/doc/v2/default_call_policies.html | 173 ++ libs/python/doc/v2/definitions.html | 102 + libs/python/doc/v2/dict.html | 152 ++ libs/python/doc/v2/docstring_options.html | 386 ++++ libs/python/doc/v2/enum.html | 234 +++ libs/python/doc/v2/errors.html | 289 +++ libs/python/doc/v2/exception_translator.html | 150 ++ libs/python/doc/v2/exec.html | 163 ++ libs/python/doc/v2/extract.html | 232 +++ libs/python/doc/v2/faq.html | 861 +++++++++ libs/python/doc/v2/feb2002.html | 367 ++++ libs/python/doc/v2/function_doc_signature.html | 216 +++ libs/python/doc/v2/handle.html | 336 ++++ libs/python/doc/v2/has_back_reference.html | 225 +++ libs/python/doc/v2/implicit.html | 163 ++ libs/python/doc/v2/import.html | 90 + libs/python/doc/v2/index.html | 20 + libs/python/doc/v2/indexing.html | 695 +++++++ libs/python/doc/v2/init.html | 251 +++ libs/python/doc/v2/instance_holder.html | 219 +++ libs/python/doc/v2/iterator.html | 398 ++++ libs/python/doc/v2/list.html | 142 ++ libs/python/doc/v2/long.html | 119 ++ libs/python/doc/v2/lvalue_from_pytype.html | 301 +++ libs/python/doc/v2/make_function.html | 210 +++ libs/python/doc/v2/manage_new_object.html | 145 ++ libs/python/doc/v2/module.html | 110 ++ libs/python/doc/v2/numeric.html | 276 +++ libs/python/doc/v2/object.html | 1121 +++++++++++ libs/python/doc/v2/opaque.html | 138 ++ libs/python/doc/v2/operators.html | 921 +++++++++ libs/python/doc/v2/overloads.html | 229 +++ libs/python/doc/v2/pickle.html | 280 +++ libs/python/doc/v2/platforms.html | 135 ++ libs/python/doc/v2/pointee.html | 119 ++ libs/python/doc/v2/progress_reports.html | 47 + libs/python/doc/v2/ptr.html | 265 +++ libs/python/doc/v2/python.html | 110 ++ libs/python/doc/v2/pytype_function.html | 370 ++++ libs/python/doc/v2/raw_function.html | 118 ++ libs/python/doc/v2/reference.html | 1192 ++++++++++++ libs/python/doc/v2/reference_existing_object.html | 180 ++ libs/python/doc/v2/register_ptr_to_python.html | 162 ++ libs/python/doc/v2/return_arg.html | 224 +++ libs/python/doc/v2/return_by_value.html | 149 ++ libs/python/doc/v2/return_internal_reference.html | 230 +++ libs/python/doc/v2/return_opaque_pointer.html | 192 ++ libs/python/doc/v2/return_value_policy.html | 167 ++ libs/python/doc/v2/scope.html | 173 ++ libs/python/doc/v2/slice.html | 246 +++ libs/python/doc/v2/ssize_t.html | 96 + libs/python/doc/v2/stl_iterator.html | 273 +++ libs/python/doc/v2/str.html | 237 +++ libs/python/doc/v2/to_python_converter.html | 227 +++ libs/python/doc/v2/to_python_indirect.html | 196 ++ libs/python/doc/v2/to_python_value.html | 103 + libs/python/doc/v2/tuple.html | 139 ++ libs/python/doc/v2/type_id.html | 224 +++ libs/python/doc/v2/with_custodian_and_ward.html | 370 ++++ libs/python/doc/v2/wrapper.html | 238 +++ 123 files changed, 29380 insertions(+) create mode 100644 libs/python/doc/Jamfile create mode 100644 libs/python/doc/PyConDC_2003/bpl.html create mode 100644 libs/python/doc/PyConDC_2003/bpl.pdf create mode 100644 libs/python/doc/PyConDC_2003/bpl.txt create mode 100644 libs/python/doc/PyConDC_2003/bpl_mods.txt create mode 100644 libs/python/doc/PyConDC_2003/default.css create mode 100644 libs/python/doc/PyConDC_2003/python_cpp_mix.jpg create mode 100644 libs/python/doc/PyConDC_2003/python_cpp_mix.png create mode 100644 libs/python/doc/boost.css create mode 100644 libs/python/doc/building.html create mode 100644 libs/python/doc/building.rst create mode 100644 libs/python/doc/index.html create mode 100644 libs/python/doc/internals.html create mode 100644 libs/python/doc/internals.rst create mode 100644 libs/python/doc/news.html create mode 100644 libs/python/doc/polymorphism.txt create mode 100644 libs/python/doc/projects.html create mode 100644 libs/python/doc/support.html create mode 100644 libs/python/doc/tutorial/doc/Jamfile.v2 create mode 100644 libs/python/doc/tutorial/doc/html/images/alert.png create mode 100644 libs/python/doc/tutorial/doc/html/images/home.png create mode 100644 libs/python/doc/tutorial/doc/html/images/jam.png create mode 100644 libs/python/doc/tutorial/doc/html/images/next.png create mode 100644 libs/python/doc/tutorial/doc/html/images/note.png create mode 100644 libs/python/doc/tutorial/doc/html/images/prev.png create mode 100644 libs/python/doc/tutorial/doc/html/images/python.png create mode 100644 libs/python/doc/tutorial/doc/html/images/smiley.png create mode 100644 libs/python/doc/tutorial/doc/html/images/tip.png create mode 100644 libs/python/doc/tutorial/doc/html/images/up.png create mode 100644 libs/python/doc/tutorial/doc/html/index.html create mode 100644 libs/python/doc/tutorial/doc/html/python/embedding.html create mode 100644 libs/python/doc/tutorial/doc/html/python/exception.html create mode 100644 libs/python/doc/tutorial/doc/html/python/exposing.html create mode 100644 libs/python/doc/tutorial/doc/html/python/functions.html create mode 100644 libs/python/doc/tutorial/doc/html/python/hello.html create mode 100644 libs/python/doc/tutorial/doc/html/python/iterators.html create mode 100644 libs/python/doc/tutorial/doc/html/python/object.html create mode 100644 libs/python/doc/tutorial/doc/html/python/techniques.html create mode 100644 libs/python/doc/tutorial/doc/tutorial.qbk create mode 100644 libs/python/doc/tutorial/index.html create mode 100644 libs/python/doc/v2/Apr2002.html create mode 100644 libs/python/doc/v2/CallPolicies.html create mode 100644 libs/python/doc/v2/Dereferenceable.html create mode 100644 libs/python/doc/v2/Extractor.html create mode 100644 libs/python/doc/v2/HolderGenerator.html create mode 100644 libs/python/doc/v2/Jun2002.html create mode 100644 libs/python/doc/v2/Mar2002.html create mode 100644 libs/python/doc/v2/May2002.html create mode 100644 libs/python/doc/v2/ObjectWrapper.html create mode 100644 libs/python/doc/v2/ResultConverter.html create mode 100644 libs/python/doc/v2/acknowledgments.html create mode 100644 libs/python/doc/v2/args.html create mode 100644 libs/python/doc/v2/call.html create mode 100644 libs/python/doc/v2/call_method.html create mode 100644 libs/python/doc/v2/callbacks.html create mode 100644 libs/python/doc/v2/callbacks.txt create mode 100644 libs/python/doc/v2/class.html create mode 100644 libs/python/doc/v2/configuration.html create mode 100644 libs/python/doc/v2/copy_const_reference.html create mode 100644 libs/python/doc/v2/copy_non_const_reference.html create mode 100644 libs/python/doc/v2/data_members.html create mode 100644 libs/python/doc/v2/def.html create mode 100644 libs/python/doc/v2/def_visitor.html create mode 100644 libs/python/doc/v2/default_call_policies.html create mode 100644 libs/python/doc/v2/definitions.html create mode 100644 libs/python/doc/v2/dict.html create mode 100644 libs/python/doc/v2/docstring_options.html create mode 100644 libs/python/doc/v2/enum.html create mode 100644 libs/python/doc/v2/errors.html create mode 100644 libs/python/doc/v2/exception_translator.html create mode 100644 libs/python/doc/v2/exec.html create mode 100644 libs/python/doc/v2/extract.html create mode 100644 libs/python/doc/v2/faq.html create mode 100644 libs/python/doc/v2/feb2002.html create mode 100644 libs/python/doc/v2/function_doc_signature.html create mode 100644 libs/python/doc/v2/handle.html create mode 100644 libs/python/doc/v2/has_back_reference.html create mode 100644 libs/python/doc/v2/implicit.html create mode 100644 libs/python/doc/v2/import.html create mode 100644 libs/python/doc/v2/index.html create mode 100644 libs/python/doc/v2/indexing.html create mode 100644 libs/python/doc/v2/init.html create mode 100644 libs/python/doc/v2/instance_holder.html create mode 100644 libs/python/doc/v2/iterator.html create mode 100644 libs/python/doc/v2/list.html create mode 100644 libs/python/doc/v2/long.html create mode 100644 libs/python/doc/v2/lvalue_from_pytype.html create mode 100644 libs/python/doc/v2/make_function.html create mode 100644 libs/python/doc/v2/manage_new_object.html create mode 100644 libs/python/doc/v2/module.html create mode 100644 libs/python/doc/v2/numeric.html create mode 100644 libs/python/doc/v2/object.html create mode 100644 libs/python/doc/v2/opaque.html create mode 100644 libs/python/doc/v2/operators.html create mode 100644 libs/python/doc/v2/overloads.html create mode 100644 libs/python/doc/v2/pickle.html create mode 100644 libs/python/doc/v2/platforms.html create mode 100644 libs/python/doc/v2/pointee.html create mode 100644 libs/python/doc/v2/progress_reports.html create mode 100644 libs/python/doc/v2/ptr.html create mode 100644 libs/python/doc/v2/python.html create mode 100644 libs/python/doc/v2/pytype_function.html create mode 100644 libs/python/doc/v2/raw_function.html create mode 100644 libs/python/doc/v2/reference.html create mode 100644 libs/python/doc/v2/reference_existing_object.html create mode 100644 libs/python/doc/v2/register_ptr_to_python.html create mode 100644 libs/python/doc/v2/return_arg.html create mode 100644 libs/python/doc/v2/return_by_value.html create mode 100644 libs/python/doc/v2/return_internal_reference.html create mode 100644 libs/python/doc/v2/return_opaque_pointer.html create mode 100644 libs/python/doc/v2/return_value_policy.html create mode 100644 libs/python/doc/v2/scope.html create mode 100644 libs/python/doc/v2/slice.html create mode 100644 libs/python/doc/v2/ssize_t.html create mode 100644 libs/python/doc/v2/stl_iterator.html create mode 100644 libs/python/doc/v2/str.html create mode 100644 libs/python/doc/v2/to_python_converter.html create mode 100644 libs/python/doc/v2/to_python_indirect.html create mode 100644 libs/python/doc/v2/to_python_value.html create mode 100644 libs/python/doc/v2/tuple.html create mode 100644 libs/python/doc/v2/type_id.html create mode 100644 libs/python/doc/v2/with_custodian_and_ward.html create mode 100644 libs/python/doc/v2/wrapper.html (limited to 'libs/python/doc') diff --git a/libs/python/doc/Jamfile b/libs/python/doc/Jamfile new file mode 100644 index 0000000000..9b7c8841aa --- /dev/null +++ b/libs/python/doc/Jamfile @@ -0,0 +1,23 @@ +# Copyright David Abrahams 2006. 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) +import docutils ; + +import path ; +sources = building.rst ; +bases = $(sources:S=) ; + +# This is a path relative to the html/ subdirectory where the +# generated output will eventually be moved. +stylesheet = "--stylesheet=../../../rst.css" ; + +for local b in $(bases) +{ + html $(b) : $(b).rst : + + "-gdt --source-url="./$(b).rst" --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript "$(stylesheet) + ; +} + +alias htmls : $(bases) ; +stage . : $(bases) ; diff --git a/libs/python/doc/PyConDC_2003/bpl.html b/libs/python/doc/PyConDC_2003/bpl.html new file mode 100644 index 0000000000..32b655bd9a --- /dev/null +++ b/libs/python/doc/PyConDC_2003/bpl.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + Loading: “Building Hybrid Systems With Boost.Python” + + + + Loading...; if nothing happens, please go to http://www.boost-consulting.com/writing/bpl.html. + + + diff --git a/libs/python/doc/PyConDC_2003/bpl.pdf b/libs/python/doc/PyConDC_2003/bpl.pdf new file mode 100644 index 0000000000..09827aff02 Binary files /dev/null and b/libs/python/doc/PyConDC_2003/bpl.pdf differ diff --git a/libs/python/doc/PyConDC_2003/bpl.txt b/libs/python/doc/PyConDC_2003/bpl.txt new file mode 100644 index 0000000000..d6921b1244 --- /dev/null +++ b/libs/python/doc/PyConDC_2003/bpl.txt @@ -0,0 +1,5 @@ +.. Copyright David Abrahams 2006. 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) + +This file has been moved to http://www.boost-consulting.com/writing/bpl.txt. diff --git a/libs/python/doc/PyConDC_2003/bpl_mods.txt b/libs/python/doc/PyConDC_2003/bpl_mods.txt new file mode 100644 index 0000000000..d42f00f8b1 --- /dev/null +++ b/libs/python/doc/PyConDC_2003/bpl_mods.txt @@ -0,0 +1,911 @@ +Copyright David Abrahams 2006. 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) + +.. This is a comment. Note how any initial comments are moved by + transforms to after the document title, subtitle, and docinfo. + +.. Need intro and conclusion +.. Exposing classes + .. Constructors + .. Overloading + .. Properties and data members + .. Inheritance + .. Operators and Special Functions + .. Virtual Functions +.. Call Policies + +++++++++++++++++++++++++++++++++++++++++++++++ + Introducing Boost.Python (Extended Abstract) +++++++++++++++++++++++++++++++++++++++++++++++ + + +.. bibliographic fields (which also require a transform): + +:Author: David Abrahams +:Address: 45 Walnut Street + Somerville, MA 02143 +:Contact: dave@boost-consulting.com +:organization: `Boost Consulting`_ +:status: This is a "work in progress" +:version: 1 +:copyright: Copyright David Abrahams 2002. All rights reserved + +:Dedication: + + For my girlfriend, wife, and partner Luann + +:abstract: + + This paper describes the Boost.Python library, a system for + C++/Python interoperability. + +.. meta:: + :keywords: Boost,python,Boost.Python,C++ + :description lang=en: C++/Python interoperability with Boost.Python + +.. contents:: Table of Contents +.. section-numbering:: + + +.. _`Boost Consulting`: http://www.boost-consulting.com + +============== + Introduction +============== + +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 +meta-language to support compile-time polymorphism, while Python is +a uniform language with convenient runtime polymorphism. + +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. + +Python provides a rich 'C' API for writers of 'C' extension modules. +Unfortunately, using this API directly for exposing C++ type and +function interfaces to Python is much more tedious than it should be. +This is mainly due to the limitations of the 'C' language. Compared to +C++ and Python, 'C' has only very rudimentary abstraction facilities. +Support for exception-handling is completely missing. One important +undesirable consequence is that 'C' extension module writers are +required to manually manage Python reference counts. Another unpleasant +consequence is a very high degree of repetition of similar code in 'C' +extension modules. Of course highly redundant code does not only cause +frustration for the module writer, but is also very difficult to +maintain. + +The limitations of the 'C' API 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 +the SIP_ package, which is specifically designed for interfacing Python +with the Qt_ graphical user interface library. Both SWIG and SIP +introduce a new specialized language for defining the inter-language +bindings. Of course being able to use a specialized language has +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. CXX is also no longer actively developed. + +In some respects Boost.Python combines ideas from SWIG and SIP with +ideas from CXX. Like SWIG and SIP, Boost.Python is a system for +wrapping C++ classes as new Python "built-in" types, and C/C++ +functions as Python functions. Like CXX, Boost.Python presents Python's +'C' API through a C++ interface. Boost.Python goes beyond the scope of +other systems with the unique support for C++ virtual functions that +are overrideable in Python, support for organizing extensions as Python +packages with a central registry for inter-language type conversions, +and a convenient mechanism for tying into Python's serialization engine +(pickle). Importantly, all this is achieved without introducing a new +syntax. Boost.Python leverages the power of C++ meta-programming +techniques to introspect about the C++ type system, and presents a +simple, IDL-like C++ interface for exposing C/C++ code in extension +modules. Boost.Python is a pure C++ library, the inter-language +bindings are defined in pure C++, and other than a C++ compiler only +Python itself is required to get started with Boost.Python. Last but +not least, Boost.Python is an unrestricted open source library. There +are no strings attached even for commercial applications. + +.. _SWIG: http://www.swig.org/ +.. _SIP: http://www.riverbankcomputing.co.uk/sip/index.php +.. _Qt: http://www.trolltech.com/ +.. _CXX: http://cxx.sourceforge.net/ + +=========================== + Boost.Python Design Goals +=========================== + +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. + +========================== + Hello Boost.Python World +========================== + +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 + 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 than +the BPL one, it's worth noting that it doesn't handle a few things +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. The BPL's dynamic type conversion registry + allows users to add arbitrary conversion methods. + +================== + Library Overview +================== + +This section outlines some of the library's major features. Except as +necessary to avoid confusion, details of library implementation are +omitted. + +------------------------------------------- + The fundamental type-conversion mechanism +------------------------------------------- + +XXX This needs to be rewritten. + +Every argument of every wrapped function requires some kind of +extraction code to convert it from Python to C++. Likewise, the +function return value has to be converted from C++ to Python. +Appropriate Python exceptions must be raised if the conversion fails. +Argument and return types are part of the function's type, and much of +this tedium can be relieved if the wrapping system can extract that +information through introspection. + +Passing a wrapped C++ derived class instance to a C++ function +accepting a pointer or reference to a base class requires knowledge of +the inheritance relationship and how to translate the address of a base +class into that of a derived class. + +------------------ + Exposing Classes +------------------ + +C++ classes and structs are exposed with a similarly-terse interface. +Given:: + + struct World + { + void set(std::string msg) { this->msg = msg; } + std::string greet() { return msg; } + std::string msg; + }; + +The following code will expose it in our extension module:: + + #include + BOOST_PYTHON_MODULE(hello) + { + class_("World") + .def("greet", &World::greet) + .def("set", &World::set) + ; + } + +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 BPL. To break it down:: + + class_("World") + +constructs an unnamed object of type ``class_`` 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 BPL type conversion registry. We might have +also written:: + + class_ 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``. + +So the example is equivalent to:: + + class_ w("World"); + w.def("greet", &World::greet); + w.def("set", &World::set); + +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 paper +will tend to stick to the terse syntax. + +For completeness, here's the wrapped class in use: + +>>> import hello +>>> planet = hello.World() +>>> planet.set('howdy') +>>> planet.greet() +'howdy' + +Constructors +============ + +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:: + + struct World + { + World(std::string msg); // added constructor + ... + +we can modify our wrapping code as follows:: + + class_("World", init()) + ... + +of course, a C++ class may have additional constructors, and we can +expose those as well by passing more instances of ``init<...>`` to +``def()``:: + + class_("World", init()) + .def(init()) + ... + +Boost.Python allows wrapped functions, member functions, and +constructors to be overloaded to mirror C++ overloading. + +Data Members and Properties +=========================== + +Any publicly-accessible data members in a C++ class can be easily +exposed as either ``readonly`` or ``readwrite`` attributes:: + + class_("World", init()) + .def_readonly("msg", &World::msg) + ... + +and can be used directly in Python: + +>>> planet = hello.World('howdy') +>>> planet.msg +'howdy' + +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. BPL 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. BPL +bridges this idiomatic gap by making Python ``property`` creation +directly available to users. So if ``msg`` were private, we could +still expose it as attribute in Python as follows:: + + class_("World", init()) + .add_property("msg", &World::greet, &World::set) + ... + +The example above mirrors the familiar usage of properties in Python +2.2+: + +>>> class World(object): +... __init__(self, msg): +... self.__msg = msg +... def greet(self): +... return self.__msg +... def set(self, msg): +... self.__msg = msg +... msg = property(greet, set) + +Operators and Special Functions +=============================== + +The ability to write arithmetic operators for user-defined types that +C++ and Python both allow the definition of has been a major factor in +the popularity of both languages for scientific computing. The +success of packages like NumPy attests to the power of exposing +operators in extension modules. In this example we'll wrap a class +representing a position in a large file:: + + class FilePos { /*...*/ }; + + // Linear offset + FilePos operator+(FilePos, int); + FilePos operator+(int, FilePos); + FilePos operator-(FilePos, int); + + // Distance between two FilePos objects + int operator-(FilePos, FilePos); + + // Offset with assignment + FilePos& operator+=(FilePos&, int); + FilePos& operator-=(FilePos&, int); + + // Comparison + bool operator<(FilePos, FilePos); + +The wrapping code looks like this:: + + class_("FilePos") + .def(self + int()) // __add__ + .def(int() + self) // __radd__ + .def(self - int()) // __sub__ + + .def(self - self) // __sub__ + + .def(self += int()) // __iadd__ + .def(self -= int()) // __isub__ + + .def(self < self); // __lt__ + ; + +The magic is performed using a simplified application of "expression +templates" [VELD1995]_, a technique originally developed by 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 processing each operation "greedily". +Boost.Python uses the same technique to build an appropriate Python +callable object based on an expression involving ``self``, which is +then added to the class. + +Inheritance +=========== + +C++ inheritance relationships can be represented to Boost.Python by adding +an optional ``bases<...>`` argument to the ``class_<...>`` template +parameter list as follows:: + + class_ >("Derived") + ... + +This has two effects: + +1. When the ``class_<...>`` is created, Python type objects + corresponding to ``Base1`` and ``Base2`` are looked up in the BPL + registry, and are used as bases for the new Python ``Derived`` type + object [#mi]_, 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. + +2. 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 + necessary 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 : + +>>> class L(list): +... def __init__(self): +... pass +... +>>> L().reverse() +>>> + +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(SomeBPLClass): +... def __init__(self): +... pass +... +>>> D().some_bpl_method() +Traceback (most recent call last): + File "", line 1, in ? +TypeError: bad argument type for built-in operation + +This happened because Boost.Python couldn't find instance data of type +``SomeBPLClass`` 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 +``SomeBPLClass.__init__(...)`` explicitly. + +Virtual Functions +================= + +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(self, "f", x); } + }; + + ... + def("calls_f", calls_f); + class_("Base") + .def("f", &Base::f, &BaseWrap::f_default) + ; + +Now here's some Python code which demonstrates: + +>>> class Derived(Base): +... def f(self, s): +... return len(s) +... +>>> calls_f(Base(), 'foo') +42 +>>> calls_f(Derived(), 'forty-two') +9 + +Things to notice about the dispatcher class: + +* 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 necessary reflects +limitations in C++'s compile-time reflection capabilities. Several +efforts are underway to write front-ends for Boost.Python which can +generate these dispatchers (and other wrapping code) automatically. +If these are successful it will mark a move away from wrapping +everything directly in pure C++ for many of our users. + +--------------- + Serialization +--------------- + +*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 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:: + + #include + + struct World + { + World(std::string a_msg) : msg(a_msg) {} + std::string greet() const { return msg; } + std::string msg; + }; + + #include + using namespace boost::python; + + struct World_picklers : pickle_suite + { + static tuple + getinitargs(World const& w) { return make_tuple(w.greet()); } + }; + + BOOST_PYTHON_MODULE(hello) + { + class_("World", init()) + .def("greet", &World::greet) + .def_pickle(World_picklers()) + ; + } + +Now let's create a ``World`` object and put it to rest on disk:: + + >>> import hello + >>> import pickle + >>> a_world = hello.World("howdy") + >>> pickle.dump(a_world, open("my_world", "w")) + +In a potentially *different script* on a potentially *different +computer* with a potentially *different operating system*:: + + >>> import pickle + >>> resurrected_world = pickle.load(open("my_world", "r")) + >>> resurrected_world.greet() + 'howdy' + +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. There is a one-to-one +correspondence between the standard pickling methods (``__getinitargs__``, +``__getstate__``, ``__setstate__``) and the functions defined by the +user in the class derived from ``pickle_suite`` (``getinitargs``, +``getstate``, ``setstate``). The ``class_::def_pickle()`` member function +is used to establish the Python bindings for all user-defined functions +simultaneously. Correct signatures for these functions are enforced at +compile time. Non-sensical combinations of the three pickle functions +are also rejected at compile time. These measures are designed to +help the user in avoiding obvious errors. + +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. + +------------------ + Object interface +------------------ + +Experienced extension module authors will be familiar with the 'C' view +of Python objects, the ubiquitous ``PyObject*``. Most if not all Python +'C' API functions involve ``PyObject*`` as arguments or return type. A +major complication is the raw reference counting interface presented to +the 'C' programmer. E.g. some API functions return *new references* and +others return *borrowed references*. It is up to the extension module +writer to properly increment and decrement reference counts. This +quickly becomes cumbersome and error prone, especially if there are +multiple execution paths. + +Boost.Python provides a type ``object`` which is essentially a high +level wrapper around ``PyObject*``. ``object`` automates reference +counting as much as possible. It also provides the facilities for +converting arbitrary C++ types to Python objects and vice versa. +This significantly reduces the learning effort for prospective +extension module writers. + +Creating an ``object`` from any other type is extremely simple:: + + object o(3); + +``object`` has templated interactions with all other types, with +automatic to-python conversions. It happens so naturally that it's +easily overlooked. + +The ``extract`` class template can be used to convert Python objects +to C++ types:: + + double x = extract(o); + +All registered user-defined conversions are automatically accessible +through the ``object`` interface. With reference to the ``World`` class +defined in previous examples:: + + object as_python_object(World("howdy")); + World back_as_c_plus_plus_object = extract(as_python_object); + +If a C++ type cannot be converted to a Python object an appropriate +exception is thrown at runtime. Similarly, an appropriate exception is +thrown if a C++ type cannot be extracted from a Python object. +``extract`` provides facilities for avoiding exceptions if this is +desired. + +The ``object::attr()`` member function is available for accessing +and manipulating attributes of Python objects. For example:: + + object planet(World()); + planet.attr("set")("howdy"); + +``planet.attr("set")`` returns a callable ``object``. ``"howdy"`` is +converted to a Python string object which is then passed as an argument +to the ``set`` method. + +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++:: + + dict d; + d["some"] = "thing"; + d["lucky_number"] = 13; + list l = d.keys(); + +This almost looks and works like regular Python code, but it is pure C++. + +================= + Thinking hybrid +================= + +For many applications runtime performance considerations are very +important. This is particularly true for most scientific applications. +Often the performance considerations dictate the use of a compiled +language for the core algorithms. Traditionally the decision to use a +particular programming language is an exclusive one. Because of the +practical and mental difficulties of combining different languages many +systems are written in just one language. This is quite unfortunate +because the price payed for runtime performance is typically a +significant overhead due to static typing. For example, our experience +shows that developing maintainable C++ code is typically much more +time-consuming and requires much more hard-earned working experience +than developing useful Python code. A related observation is that many +compiled packages are augmented by some type of rudimentary scripting +layer. These ad hoc solutions clearly show that many times a compiled +language alone does not get the job done. On the other hand it is also +clear that a pure Python implementation is too slow for numerically +intensive production code. + +Boost.Python enables us to *think hybrid* when developing new +applications. Python can be used for rapidly prototyping a +new application. Python's ease of use and the large pool of standard +libraries give us a head start on the way to a first working system. If +necessary, the working procedure can be used to discover the +rate-limiting algorithms. 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 a compiled language. 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 (scitbx) that we will describe elsewhere. 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. We expect this +trend to continue, as illustrated qualitatively in this figure: + +.. image:: python_cpp_mix.png + +This figure shows the 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. The increasing ability to solve new problems +mostly with the easy-to-use Python language rather than a necessarily +more arcane statically typed language is the return on the investment +of learning how to use Boost.Python. The ability to solve some problems +entirely using only Python will enable a larger group of people to +participate in the rapid development of new applications. + +============= + Conclusions +============= + +The examples in this paper illustrate that Boost.Python enables +seamless interoperability between C++ and Python. Importantly, this is +achieved without introducing a third syntax: the Python/C++ interface +definitions are written in pure C++. This avoids any problems with +parsing the C++ code to be interfaced to Python, yet the interface +definitions are concise and maintainable. Freed from most of the +development-time penalties of crossing a language boundary, software +designers can take full advantage of two rich and complimentary +language environments. In practice it turns out that some things are +very difficult to do with pure Python/C (e.g. an efficient array +library with an intuitive interface in the compiled language) and +others are very difficult to do with pure C++ (e.g. serialization). +If one has the luxury of being able to design a software system as a +hybrid system from the ground up there are many new ways of avoiding +road blocks in one language or the other. + +.. I'm not ready to give up on all of this quite yet + +.. Perhaps one day we'll have a language with the simplicity and + expressive power of Python and the compile-time muscle of C++. Being + able to take advantage of all of these facilities without paying the + mental and development-time penalties of crossing a language barrier + would bring enormous benefits. Until then, interoperability tools + like Boost.Python can help lower the barrier and make the benefits of + both languages more accessible to both communities. + +=========== + Footnotes +=========== + +.. [#mi] For hard-core new-style class/extension module writers it is + worth noting that the normal requirement that all extension classes + with data form a layout-compatible single-inheritance chain is + lifted for Boost.Python extension classes. Clearly, either + ``Base1`` or ``Base2`` has to occupy a different offset in the + ``Derived`` class instance. This is possible because the wrapped + part of BPL extension class instances is never assumed to have a + fixed offset within the wrapper. + +=========== + Citations +=========== + +.. [VELD1995] T. Veldhuizen, "Expression Templates," C++ Report, + Vol. 7 No. 5 June 1995, pp. 26-31. + http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html diff --git a/libs/python/doc/PyConDC_2003/default.css b/libs/python/doc/PyConDC_2003/default.css new file mode 100644 index 0000000000..f8109bbd33 --- /dev/null +++ b/libs/python/doc/PyConDC_2003/default.css @@ -0,0 +1,188 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:copyright: This stylesheet has been placed in the public domain. + +boostinspect:nolicense + +Default cascading style sheet for the HTML output of Docutils. +*/ + +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } diff --git a/libs/python/doc/PyConDC_2003/python_cpp_mix.jpg b/libs/python/doc/PyConDC_2003/python_cpp_mix.jpg new file mode 100644 index 0000000000..755a9605b8 Binary files /dev/null and b/libs/python/doc/PyConDC_2003/python_cpp_mix.jpg differ diff --git a/libs/python/doc/PyConDC_2003/python_cpp_mix.png b/libs/python/doc/PyConDC_2003/python_cpp_mix.png new file mode 100644 index 0000000000..fd74cbb224 Binary files /dev/null and b/libs/python/doc/PyConDC_2003/python_cpp_mix.png differ diff --git a/libs/python/doc/boost.css b/libs/python/doc/boost.css new file mode 100644 index 0000000000..6c3e9808ea --- /dev/null +++ b/libs/python/doc/boost.css @@ -0,0 +1,63 @@ +/* Copyright David Abrahams 2006. 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) +*/ +H1 +{ + FONT-SIZE: 200% + COLOR: #00007f +} +H2 +{ + FONT-SIZE: 150%; +} +H3 +{ + FONT-SIZE: 125%; +} +H4 +{ + FONT-SIZE: 108%; +} +BODY +{ + FONT-SIZE: 100%; + BACKGROUND-COLOR: #ffffff +} +PRE +{ + MARGIN-LEFT: 2pc; + FONT-SIZE: 80%; + BACKGROUND-COLOR: #dfffff +} +CODE +{ + FONT-SIZE: 95%; + white-space: pre +} +.index +{ + TEXT-ALIGN: left +} +.page-index +{ + TEXT-ALIGN: left +} +.definition +{ + TEXT-ALIGN: left +} +.footnote +{ + FONT-SIZE: 66%; + VERTICAL-ALIGN: super; + TEXT-DECORATION: none +} +.function-semantics +{ + CLEAR: left +} +.metafunction-semantics +{ + CLEAR: left +} diff --git a/libs/python/doc/building.html b/libs/python/doc/building.html new file mode 100644 index 0000000000..e2c48847f1 --- /dev/null +++ b/libs/python/doc/building.html @@ -0,0 +1,636 @@ + + + + + + +Boost C++ Libraries: Boost.Python Build and Test HOWTO + + + +
+

Boost.Python Build and Test HOWTO

+ + + + + + +
+

1   Requirements

+

Boost.Python requires Python 2.21 or newer.

+
+
+

2   Background

+

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().

+
+
+

3   No-Install Quickstart

+

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.1   Basic Procedure

+
    +
  1. Get Boost; see sections 1 and 2 [Unix/Linux, Windows] of the +Boost Getting Started Guide.

    +
  2. +
  3. Get the bjam build driver. See section 5 [Unix/Linux, +Windows] of the Boost Getting Started Guide.

    +
  4. +
  5. cd into the libs/python/example/quickstart/ directory of your +Boost installation, which contains a small example project.

    +
  6. +
  7. Invoke bjam. Replace the “stage“ argument from the +example invocation from section 5 of the 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:

    +
    +C:\boost_1_34_0\…\quickstart> bjam toolset=msvc --verbose-test test
    +
    +

    and on Unix variants, perhaps,

    +
    +~/boost_1_34_0/…/quickstart$ bjam toolset=gcc --verbose-test test
    +
    +
  8. +
+
+

Note to Windows Users

+

For the sake of concision, the rest of this guide will use +unix-style forward slashes in pathnames instead of the +backslashes with which you 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.

+
+
+

3.2   In Case of Trouble

+

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:

+ +
+
+

3.3   In Case Everything Seemed to Work

+

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 documentation, trying out what you've +learned about the API by modifying the quickstart project.

+
+
+

3.4   Modifying the Example Project

+

If you're content to keep your extension module forever in one +source file called extending.cpp, inside your Boost +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.

+
+

Relocate the Project

+

You'll probably want to copy this project elsewhere so you can +change it without modifying your Boost distribution. To do that, +simply

+
    +
  1. copy the entire libs/python/example/quickstart/ directory +into a new directory.
  2. +
  3. 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 +libs/python/example/quickstart/ directory.
  4. +
+

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

+
+../../../../tools/build/v2
+
+

to

+
+/home/dave/boost_1_34_0/tools/build/v2
+
+

and change the first path in Jamroot from

+
+../../../..
+
+

to

+
+/home/dave/boost_1_34_0
+
+
+
+

Add New or Change Names of Existing Source Files

+

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.cpp file2.cpp file3.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.

+
+
+

Change the Name of your Extension Module

+

The name of the extension module is determined by two things:

+
    +
  1. the name in Jamroot immediately following python-extension, and
  2. +
  3. the name passed to BOOST_PYTHON_MODULE in extending.cpp.
  4. +
+

To change the name of the extension module from extending to +hello, you'd edit Jamroot, changing

+
+python-extension extending : extending.cpp ;
+
+

to

+
+python-extension hello : extending.cpp ;
+
+

and you'd edit extending.cpp, changing

+
+BOOST_PYTHON_MODULE(extending)
+
+

to

+
+BOOST_PYTHON_MODULE(hello)
+
+
+
+
+
+

4   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.

+
+
+

5   Configuring Boost.Build

+

As described in the Boost.Build reference manual, a file called +user-config.jam in your home directory6 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.

+
+

Users of Unix-Variant OSes

+

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.4 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

+
+import toolset : using ;
+using python ;
+
+

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.

+
+

5.1   Python Configuration Parameters

+

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 using python.

+
+
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.
+
+
+
+

5.2   Examples

+

Note that in the examples below, case and especially whitespace are +significant.

+
    +
  • If you have both python 2.5 and python 2.4 installed, +user-config.jam might contain:

    +
    +using python : 2.5 ;  # Make both versions of Python available
    +
    +using python : 2.4 ;  # To build with python 2.4, add python=2.4
    +                      # to your command line.
    +
    +

    The first version configured (2.5) becomes the default. To build +against python 2.4, add python=2.4 to the bjam command line.

    +
  • +
  • If you have python installed in an unusual location, you might +supply the path to the interpreter in the cmd-or-prefix +parameter:

    +
    +using python : : /usr/local/python-2.6-beta/bin/python ;
    +
    +
  • +
  • If you have a separate build of Python for use with a particular +toolset, you might supply that toolset in the condition +parameter:

    +
    +using python ;  # use for most toolsets
    +
    +# Use with Intel C++ toolset
    +using python
    +     : # version
    +     : c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix
    +     : # includes
    +     : # libraries
    +     : <toolset>intel # condition
    +     ;
    +
    +
  • +
  • If you have downloaded the Python sources and built both the +normal and the “python debugging” builds from source on +Windows, you might see:

    +
    +using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python ;
    +using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python_d
    +  : # includes
    +  : # libs
    +  : <python-debugging>on ;
    +
    +
  • +
  • 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:

    +
    +# windows installation
    +using python ;
    +
    +# cygwin installation
    +using python : : c:\\cygwin\\bin\\python2.5 : : : <target-os>cygwin ;
    +
    +

    when you put target-os=cygwin in your build request, it should build +with the cygwin version of python:5

    +
    +

    bjam target-os=cygwin toolset=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.

    +
  • +
  • Note that because of the way Boost.Build currently selects target +alternatives, you might have be very explicit in your build +requests. For example, given:

    +
    +using python : 2.5 ; # a regular windows build
    +using python : 2.4 : : : : <target-os>cygwin ;
    +
    +

    building with

    +
    +bjam target-os=cygwin
    +
    +

    will yield an error. Instead, you'll need to write:

    +
    +bjam target-os=cygwin/python=2.4
    +
    +
  • +
+
+
+
+

6   Choosing a Boost.Python Library Binary

+

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.2

+
+

6.1   The Dynamic Binary

+

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.3
  • +
  • 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.
  • +
+
+
+

6.2   The Static Binary

+

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).
    • +
    +
  • +
+
+
+
+

7   #include Issues

+
    +
  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. +
  3. 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.
  4. +
+
+
+

8   Python Debugging Builds

+

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,7 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.

+
+
+

9   Testing Boost.Python

+

To run the full test suite for Boost.Python, invoke bjam in the +libs/python/test subdirectory of your Boost distribution.

+
+
+

10   Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users

+

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.

+
+ + + + + +
[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.
+ + + + + +
[2]

Information about how to identify the +static and dynamic builds of Boost.Python:

+ +
+ + + + + +
[3]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.
+ + + + + +
[4]configure overwrites the existing +user-config.jam in your home directory +(if any) after making a backup of the old version.
+ + + + + +
[5]Note that the <target-os>cygwin feature is +different from the <flavor>cygwin subfeature of the gcc +toolset, and you might need handle both explicitly if you also +have a MinGW GCC installed.
+ + + + + +
[6]

Windows users, your home directory can be +found by typing:

+
+ECHO %HOMEDRIVE%%HOMEPATH%
+
+

into a command prompt window.

+
+ + + + + +
[7]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. +
+
+
+ + + diff --git a/libs/python/doc/building.rst b/libs/python/doc/building.rst new file mode 100644 index 0000000000..1e2c7d42f2 --- /dev/null +++ b/libs/python/doc/building.rst @@ -0,0 +1,680 @@ +.. Copyright David Abrahams 2006. 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) + +============================================== + |(logo)|__ Boost.Python Build and Test HOWTO +============================================== + +.. |(logo)| image:: ../../../boost.png + :alt: Boost C++ Libraries: + :class: boost-logo + +__ ../index.html + + +.. section-numbering:: + :depth: 2 + +.. contents:: Contents + :depth: 2 + :class: sidebar small + +.. |newer| replace:: *newer* + +Requirements +============ + +Boost.Python requires `Python 2.2`_ [#2.2]_ *or* |newer|__. + +.. _Python 2.2: http://www.python.org/2.2 +__ http://www.python.org + +Background +========== + +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. + +.. _extending: http://www.python.org/doc/current/ext/intro.html +.. _embedding: http://www.python.org/doc/current/ext/embedding.html + +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. + +__ http://www.python.org/doc/current/ext/extending-with-embedding.html + +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()``. + +.. _quickstart: + +No-Install Quickstart +===================== + +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. + +.. .. raw:: html + +
+ +.. 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 + + .. parsed-literal:: + + ``-a -o``\ *filename* + + options to dump the build commands it executes to a file, so + you can see what your alternate build system needs to do. + +.. .. raw:: html + +
+ +.. _Boost.Build: ../../../tools/build/index.html + +Basic Procedure +--------------- + +1. Get Boost; see sections 1 and 2 [`Unix/Linux`__, `Windows`__\ ] of the + Boost `Getting Started Guide`_. + + __ ../../../more/getting_started/unix-variants.html#get-boost + __ ../../../more/getting_started/windows.html#get-boost + +2. Get the ``bjam`` build driver. See section 5 [`Unix/Linux`__, + `Windows`__\ ] of the Boost `Getting Started Guide`_. + + __ ../../../more/getting_started/unix-variants.html#prepare-to-use-a-boost-library-binary + __ ../../../more/getting_started/windows.html#prepare-to-use-a-boost-library-binary + + +3. cd into the ``libs/python/example/quickstart/`` directory of your + Boost installation, which contains a small example project. + +4. Invoke ``bjam``. Replace the “\ ``stage``\ “ argument from the + example invocation from section 5 of the `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: + + .. parsed-literal:: + + C:\\boost_1_34_0\\…\\quickstart> **bjam toolset=msvc --verbose-test test** + + and on Unix variants, perhaps, + + .. parsed-literal:: + + ~/boost_1_34_0/…/quickstart$ **bjam toolset=gcc --verbose-test test** + +.. Admonition:: Note to Windows Users + + For the sake of concision, the rest of this guide will use + unix-style forward slashes in pathnames instead of the + backslashes with which you may be more familiar. The forward + slashes should work everywhere except in `Command Prompt`_ + windows, where you should use backslashes. + + .. _Command Prompt: ../../../more/getting_started/windows.html#command-prompt + +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. + +.. _Getting Started Guide: ../../../more/getting_started/index.html + +In Case of Trouble +------------------ + +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: + +* The `Boost.Build mailing list`__ for issues related to Boost.Build +* The Python `C++ Sig`__ for issues specifically related to Boost.Python + +__ http://www.boost.org/more/mailing_lists.htm#jamboost +__ http://www.boost.org/more/mailing_lists.htm#cplussig + +In Case Everything Seemed to Work +--------------------------------- + +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 documentation`_, trying out what you've +learned about the API by modifying the quickstart project. + +.. _reference documentation: v2/reference.html +.. _tutorial: tutorial/index.html + +Modifying the Example Project +----------------------------- + +If you're content to keep your extension module forever in one +source file called |extending.cpp|_, inside your Boost +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. + +.. |boost-build.jam| replace:: ``boost-build.jam`` +.. _boost-build.jam: ../example/quickstart/boost-build.jam + +.. |Jamroot| replace:: ``Jamroot`` +.. _Jamroot: ../example/quickstart/Jamroot + +.. |extending.cpp| replace:: ``extending.cpp`` +.. _extending.cpp: ../example/quickstart/extending.cpp + +Relocate the Project +.................... + +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 ``libs/python/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 + ``libs/python/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 + +.. parsed-literal:: + + **../../../..**\ /tools/build/v2 + +to + +.. parsed-literal:: + + **/home/dave/boost_1_34_0**\ /tools/build/v2 + +and change the first path in |Jamroot|_ from + +.. parsed-literal:: + + **../../../..** + +to + +.. parsed-literal:: + + **/home/dave/boost_1_34_0** + +Add New or Change Names of Existing Source Files +................................................ + +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.cpp file2.cpp file3.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|_. + +Change the Name of your Extension Module +........................................ + +The name of the extension module is determined by two things: + +1. the name in |Jamroot|_ immediately following ``python-extension``, and +2. the name passed to ``BOOST_PYTHON_MODULE`` in |extending.cpp|_. + +To change the name of the extension module from ``extending`` to +``hello``, you'd edit |Jamroot|_, changing + +.. parsed-literal:: + + python-extension **extending** : extending.cpp ; + +to + +.. parsed-literal:: + + python-extension **hello** : extending.cpp ; + +and you'd edit extending.cpp, changing + +.. parsed-literal:: + + BOOST_PYTHON_MODULE(\ **extending**\ ) + +to + +.. parsed-literal:: + + BOOST_PYTHON_MODULE(\ **hello**\ ) + +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. + +.. _header-only: ../../../more/getting_started/windows.html#header-only-libraries + +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. + + +Configuring Boost.Build +======================= + +As described in the `Boost.Build reference manual`__, a file called +``user-config.jam`` in your home directory [#home-dir]_ 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. + +__ http://www.boost.orgdoc/html/bbv2/advanced.html#bbv2.advanced.configuration + +.. Admonition:: Users of Unix-Variant OSes + + 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. [#overwrite]_ 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 :: + + import toolset : using ; + using python ; + +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. + +Python Configuration Parameters +------------------------------- + +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 ``using python``. + +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. + +.. |python-debugging| replace:: ```` + +__ https://wiki.ubuntu.com/PyDbgBuilds + + +Examples +-------- + +Note that in the examples below, case and *especially whitespace* are +significant. + +- If you have both python 2.5 and python 2.4 installed, + ``user-config.jam`` might contain:: + + using python : 2.5 ; # Make both versions of Python available + + using python : 2.4 ; # To build with python 2.4, add python=2.4 + # to your command line. + + The first version configured (2.5) becomes the default. To build + against python 2.4, add ``python=2.4`` to the ``bjam`` command line. + +- If you have python installed in an unusual location, you might + supply the path to the interpreter in the ``cmd-or-prefix`` + parameter:: + + using python : : /usr/local/python-2.6-beta/bin/python ; + +- If you have a separate build of Python for use with a particular + toolset, you might supply that toolset in the ``condition`` + parameter:: + + using python ; # use for most toolsets + + # Use with Intel C++ toolset + using python + : # version + : c:\\Devel\\Python-2.5-IntelBuild\\PCBuild\\python # cmd-or-prefix + : # includes + : # libraries + : intel # condition + ; + + +- If you have downloaded the Python sources and built both the + normal and the “\ `python debugging`_\ ” builds from source on + Windows, you might see:: + + using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python ; + using python : 2.5 : C:\\src\\Python-2.5\\PCBuild\\python_d + : # includes + : # libs + : on ; + +- 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 + ``cygwin`` in the ``condition`` parameter + for the cygwin python installation:: + + # windows installation + using python ; + + # cygwin installation + using python : : c:\\cygwin\\bin\\python2.5 : : : cygwin ; + + when you put target-os=cygwin in your build request, it should build + with the cygwin version of python: [#flavor]_ + + bjam target-os=cygwin toolset=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. + +- Note that because of `the way Boost.Build currently selects target + alternatives`__, you might have be very explicit in your build + requests. For example, given:: + + using python : 2.5 ; # a regular windows build + using python : 2.4 : : : : cygwin ; + + building with :: + + bjam target-os=cygwin + + will yield an error. Instead, you'll need to write:: + + bjam target-os=cygwin/python=2.4 + +.. _Cygwin: http://cygwin.com + +__ http://zigzag.cs.msu.su/boost.build/wiki/AlternativeSelection + +Choosing a Boost.Python Library Binary +====================================== + +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. [#naming]_ + +The Dynamic Binary +------------------ + +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. [#toolset-specific]_ + +- 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. + +The Static Binary +----------------- + +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). + +``#include`` Issues +=================== + +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. + +.. _python-debugging: +.. _python debugging: + +Python Debugging Builds +======================= + +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, [#get-debug-build]_ 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. + +Testing Boost.Python +==================== + +To run the full test suite for Boost.Python, invoke ``bjam`` in the +``libs/python/test`` subdirectory of your Boost distribution. + +Notes for MinGW (and Cygwin with -mno-cygwin) GCC Users +======================================================= + +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. + +__ http://www.python.org/doc/current/inst/index.html + +----------------------------- + +.. [#2.2] 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. + +.. [#naming] Information about how to identify the + static and dynamic builds of Boost.Python: + + * `on Windows`__ + * `on Unix variants`__ + + __ ../../../more/getting_started/windows.html#library-naming + __ ../../../more/getting_started/unix-variants.html#library-naming + +.. [#toolset-specific] 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. + +.. [#overwrite] ``configure`` overwrites the existing + ``user-config.jam`` in your home directory + (if any) after making a backup of the old version. + +.. [#flavor] Note that the ``cygwin`` feature is + different from the ``cygwin`` subfeature of the ``gcc`` + toolset, and you might need handle both explicitly if you also + have a MinGW GCC installed. + +.. [#home-dir] Windows users, your home directory can be + found by typing:: + + ECHO %HOMEDRIVE%%HOMEPATH% + + into a `command prompt`_ window. + +.. [#get-debug-build] 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. diff --git a/libs/python/doc/index.html b/libs/python/doc/index.html new file mode 100644 index 0000000000..e600366fec --- /dev/null +++ b/libs/python/doc/index.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + Boost.Python + + + + + + + + + + + + + + + +
+

+

+
+

Boost.Python

+ +

Index

+
+ +
+

+ + Search + +
+
+ + + + + +
+ + + GooglePowered + + + + + + +
+ + +

+
+ +
+
+ + +

Synopsis

+ Welcome to version 2 of Boost.Python, a C++ library which enables + seamless interoperability between C++ and the Python programming language. The new version + has been rewritten from the ground up, with a more convenient and + flexible interface, and many new capabilities, including support for: + +
    +
  • References and Pointers
  • + +
  • Globally Registered Type Coercions
  • + +
  • Automatic Cross-Module Type Conversions
  • + +
  • Efficient Function Overloading
  • + +
  • C++ to Python Exception Translation
  • + +
  • Default Arguments
  • + +
  • Keyword Arguments
  • + +
  • Manipulating Python objects in C++
  • + +
  • Exporting C++ Iterators as Python Iterators
  • + +
  • Documentation Strings
  • +
+ The development of these features was funded in part by grants to Boost Consulting from the Lawrence Livermore National Laboratories + and by the Computational Crystallography + Initiative at Lawrence Berkeley National Laboratories. + +
+ +

Contents

+ +
+
Tutorial Introduction
+ +
Building and Testing
+ +
Reference Manual
+ +
Suites:
+
+ +
+ +
Configuration Information
+ +
Known Working Platforms and + Compilers
+ +
Definitions
+ +
Projects using Boost.Python
+ +
Support Resources
+ +
Frequently Asked Questions (FAQs)
+ +
Py++ Boost.Python code generator
+ +
Pyste Boost.Python code generator (no longer maintained)
+ +
Internals Documentation
+ +
News/Change Log
+ +
TODO list
+ +
LLNL Progress Reports
+ +
Acknowledgments
+
+
+ +

Articles

+ + "Building Hybrid + Systems With Boost Python", by Dave Abrahams and Ralf + W. Grosse-Kunstleve (PDF) + +
+ +

Revised + + 26 August, 2003 + +

+ +

© Copyright Dave + Abrahams 2002-2003.

+ + + diff --git a/libs/python/doc/internals.html b/libs/python/doc/internals.html new file mode 100644 index 0000000000..2f7d760705 --- /dev/null +++ b/libs/python/doc/internals.html @@ -0,0 +1,186 @@ + + + + + + +Boost.Python Internals Boost + + + + + + + + diff --git a/libs/python/doc/internals.rst b/libs/python/doc/internals.rst new file mode 100644 index 0000000000..2438d5ffbc --- /dev/null +++ b/libs/python/doc/internals.rst @@ -0,0 +1,182 @@ +=================================== + Boost.Python_ Internals |(logo)|__ +=================================== + +.. |(logo)| image:: ../../../boost.png + :alt: Boost + :class: boost-logo + +__ ../../../index.htm + +.. _`Boost.Python`: index.html + +.. _license: ../../../LICENSE_1_0.txt + + +------------------------------------------------------- +A conversation between Brett Calcott and David Abrahams +------------------------------------------------------- + +:copyright: Copyright David Abrahams and Brett Calcott 2003. See + accompanying license_ for terms of use. + +In both of these cases, I'm quite capable of reading code - but the +thing I don't get from scanning the source is a sense of the +architecture, both structurally, and temporally (er, I mean in what +order things go on). + +1) What happens when you do the following:: + + struct boring {}; + ...etc... + class_("boring") + ; + +There seems to be a fair bit going on. + + - Python needs a new ClassType to be registered. + - We need to construct a new type that can hold our boring struct. + - Inward and outward converters need to be registered for the type. + +Can you gesture in the general direction where these things are done? + + I only have time for a "off-the-top-of-my-head" answer at the moment; + I suggest you step through the code with a debugger after reading this + to see how it works, fill in details, and make sure I didn't forget + anything. + + A new (Python) subclass of Boost.Python.Instance (see + libs/python/src/object/class.cpp) is created by invoking + Boost.Python.class, the metatype:: + + >>> boring = Boost.Python.class( + ... 'boring' + ... , bases_tuple # in this case, just () + ... , { + ... '__module__' : module_name + ... , '__doc__' : doc_string # optional + ... } + ... ) + + A handle to this object is stuck in the m_class_object field + of the registration associated with ``typeid(boring)``. The + registry will keep that object alive forever, even if you + wipe out the 'boring' attribute of the extension module + (probably not a good thing). + + Because you didn't specify ``class``, a to-python converter for boring is registered which + copies its argument into a value_holder held by the the + Python boring object. + + Because you didn't specify ``class(no_init)``, + an ``__init__`` function object is added to the class + dictionary which default-constructs a boring in a + value_holder (because you didn't specify some smart pointer + or derived wrapper class as a holder) held by the Python + boring object. + + ``register_class_from_python`` is used to register a + from-python converter for ``shared_ptr``. + ``boost::shared_ptr``\ s are special among smart pointers + because their Deleter argument can be made to manage the + whole Python object, not just the C++ object it contains, no + matter how the C++ object is held. + + If there were any ``bases<>``, we'd also be registering the + relationship between these base classes and boring in the + up/down cast graph (``inheritance.[hpp/cpp]``). + + In earlier versions of the code, we'd be registering lvalue + from-python converters for the class here, but now + from-python conversion for wrapped classes is handled as a + special case, before consulting the registry, if the source + Python object's metaclass is the Boost.Python metaclass. + + Hmm, that from-python converter probably ought to be handled + the way class converters are, with no explicit conversions + registered. + +2) Can you give a brief overview of the data structures that are + present in the registry + + The registry is simple: it's just a map from typeid -> + registration (see boost/python/converter/registrations.hpp). + ``lvalue_chain`` and ``rvalue_chain`` are simple endogenous + linked lists. + + If you want to know more, just ask. + + If you want to know about the cast graph, ask me something specific in + a separate message. + + and an overview of the process that happens as a type makes its + way from c++ to python and back again. + + Big subject. I suggest some background reading: look for relevant + info in the LLNL progress reports and the messages they link to. + Also, + + http://mail.python.org/pipermail/c++-sig/2002-May/001023.html + + http://mail.python.org/pipermail/c++-sig/2002-December/003115.html + + http://aspn.activestate.com/ASPN/Mail/Message/1280898 + + http://mail.python.org/pipermail/c++-sig/2002-July/001755.html + + from c++ to python: + + It depends on the type and the call policies in use or, for + ``call<>(...)``, ``call_method<>(...)``, or ``object(...)``, if + ``ref`` or ``ptr`` is used. There are also two basic + categories to to-python conversion, "return value" conversion + (for Python->C++ calls) and "argument" conversion (for + C++->Python calls and explicit ``object()`` conversions). The + behavior of these two categories differs subtly in various ways + whose details I forget at the moment. You can probably find + the answers in the above references, and certainly in the code. + + The "default" case is by-value (copying) conversion, which uses + to_python_value as a to-python converter. + + Since there can sensibly be only one way to convert any type + to python (disregarding the idea of scoped registries for the + moment), it makes sense that to-python conversions can be + handled by specializing a template. If the type is one of + the types handled by a built-in conversion + (builtin_converters.hpp), the corresponding template + specialization of to_python_value gets used. + + Otherwise, to_python_value uses the ``m_to_python`` + function in the registration for the C++ type. + + Other conversions, like by-reference conversions, are only + available for wrapped classes, and are requested explicitly by + using ``ref(...)``, ``ptr(...)``, or by specifying different + CallPolicies for a call, which can cause a different to-python + converter to be used. These conversions are never registered + anywhere, though they do need to use the registration to find + the Python class corresponding to the C++ type being referred + to. They just build a new Python instance and stick the + appropriate Holder instance in it. + + + from python to C++: + + Once again I think there is a distinction between "return value" + and "argument" conversions, and I forget exactly what that is. + + What happens depends on whether an lvalue conversion is needed + (see http://mail.python.org/pipermail/c++-sig/2002-May/001023.html) + All lvalue conversions are also registered in a type's rvalue + conversion chain, since when an rvalue will do, an lvalue is + certainly good enough. + + An lvalue conversion can be done in one step (just get me the + pointer to the object - it can be ``NULL`` if no conversion is + possible) while an rvalue conversion requires two steps to + support wrapped function overloading and multiple converters for + a given C++ target type: first tell me if a conversion is + possible, then construct the converted object as a second step. + diff --git a/libs/python/doc/news.html b/libs/python/doc/news.html new file mode 100644 index 0000000000..da57caeb30 --- /dev/null +++ b/libs/python/doc/news.html @@ -0,0 +1,371 @@ + + + + + + + + + + + + Boost.Python - News/Change Log + + + + + + + + + +
+

+

+
+

Boost.Python

+ +

News/Change Log

+
+
+ +
+ +
Current SVN
+
+
    +
  • Python 3 support:
  • +
      +
    • All the current Boost.Python test cases passed. Extension modules using + Boost.Python expected to support Python 3 smoothly.
    • +
    • Introduced object.contains where x.contains(y) + is equivalent to Python code y in x. + Now dict.has_key is just a wrapper of object.contains. +
    • +
    • When building against Python 3, str.decode will be removed.
    • +
    • When building against Python 3, the original signature of list.sort, which is: +
      void sort(object_cref cmpfunc);
      + will change to: +
      void sort(args_proxy const &args, kwds_proxy const &kwds);
      + + This is because in Python 3 list.sort requires all its arguments be keyword arguments. + So you should call it like this: +
      x.sort(*tuple(), **dict(make_tuple(make_tuple("reverse", true))));
      + +
    • +
    • According to PEP 3123, + when building Boost.Python against Python older than 2.6, the following macros will + be defined in Boost.Python header: +
      +# define Py_TYPE(o)    (((PyObject*)(o))->ob_type)
      +# define Py_REFCNT(o)  (((PyObject*)(o))->ob_refcnt)
      +# define Py_SIZE(o)    (((PyVarObject*)(o))->ob_size)
      + So extension writers can use these macro directly, to make code clean and compatible with Python 3. +
    • +
    +
+
+ +
1.39.0 Release
+ +
+
    +
  • Pythonic signatures are now automatically appended to the + docstrings. + +
  • Use docstring_options.hpp header + control the content of docstrings. + +
  • This new feature increases the size of the modules by about 14%. + If this is not acceptable it can be turned off by defining the macro + BOOST_PYTHON_NO_PY_SIGNATURES. Modules compiled with and without the macro + defined are compatible. +
  • +
  • If BOOST_PYTHON_NO_PY_SIGNATURES is undefined, this version defines the + macro BOOST_PYTHON_SUPPORTS_PY_SIGNATURES. This allows writing code that will compile + with older version of Boost.Python (see here). +
  • +
  • By defining BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE, and at a cost + of another 14% size increase, proper pythonic type is generated for the "self" + parameter of the __init__ methods. +
  • + +
  • To support this new feature changes were made to the + to_python_converter.hpp, + default_call_policies, + ResultConverter, + CallPolicies and some others. + Efforts were made not to have interface breaking changes. +
  • + +
+
+ +
12 May 2007 - 1.34.0 release
+ +
+
    +
  • C++ signatures are now automatically appended to the + docstrings. + +
  • New docstring_options.hpp header to + control the content of docstrings. + +
  • Support for converting void* to/from python, + with opaque_pointer_converter + as the return value policy. Thanks to Niall Douglas for the + initial patch. +
+
+ +
19 October 2005 - 1.33.1 release
+ +
+
    +
  • wrapper<T> can now be used as expected with a + held type of some-smart-pointer<T>
  • + +
  • The build now assumes Python 2.4 by default, rather than 2.2
  • + +
  • Support Python that's built without Unicode support
  • + +
  • Support for wrapping classes with overloaded address-of + (&) operators
  • +
+
+ +
14 August 2005 - 1.33 release
+ +
+
    +
  • Support for docstrings on nonstatic properties.
  • + +
  • We now export the client-provided docstrings for + init<optional<> > and + XXX_FUNCTION_OVERLOADS() for only the last + overload.
  • + +
  • Fixed some support for Embedded VC++ 4
  • + +
  • Better support for rvalue from-python conversions of shared_ptr: + always return a pointer that holds the owning python object *unless* + the python object contains a NULL shared_ptr holder of the right + type.
  • + +
  • Support for exposing vector<T*> with the + indexing suite.
  • + +
  • Support for GCC-3.3 on MacOS.
  • + +
  • updated visual studio project build file to include two new files + (slice.cpp and wrapper.cpp)
  • + +
  • Added search feature to the index page.
  • + +
  • Numerous fixes to the tutorial
  • + +
  • Numerous workarounds for MSVC 6 and 7, GCC 2.96, and EDG + 2.45
  • +
+
+ +
11 March 2005
+ +
+
    +
  • Added a hack that will fool PyDoc into working with Boost.Python, + thanks to Nick Rasmussen
  • +
+
+ +
19 November 2004 - 1.32 release
+ +
+
    +
  • Updated to use the Boost Software License.
  • + +
  • A new, + better method of wrapping classes with virtual functions has been + implemented.
  • + +
  • Support for upcoming GCC symbol export control features have been + folded in, thanks to Niall Douglas.
  • + +
  • Improved support for std::auto_ptr-like types.
  • + +
  • The Visual C++ bug that makes top-level cv-qualification + of function parameter types part of the function type has been worked + around.
  • + +
  • Components used by other libraries have been moved out of + python/detail and into boost/detail to + improve dependency relationships.
  • + +
  • Miscellaneous bug fixes and compiler workarounds.
  • +
+
+ +
8 Sept 2004
+ +
Support for Python's Bool type, thanks to Daniel Holth.
+ +
11 Sept 2003
+ +
+
    +
  • Changed the response to multiple to-python converters being + registered for the same type from a hard error into warning; + Boost.Python now reports the offending type in the message.
  • + +
  • Added builtin std::wstring conversions
  • + +
  • Added std::out_of_range => Python + IndexError exception conversion, thanks to Raoul Gough
  • +
+
+ +
9 Sept 2003
+ +
Added new str
+ +
constructors which take a range of characters, allowing strings + containing nul ('\0') characters.
+ +
8 Sept 2003
+ +
Added the ability to create methods from function objects (with an + operator()); see the make_function docs for + more info.
+ +
10 August 2003
+ +
Added the new properties unit tests contributed by + Roman Yakovenko and + documented add_static_property at his urging.
+ +
1 August 2003
+ +
+ Added the new arg class contributed by Nikolay Mladenov which supplies the + ability to wrap functions that can be called with ommitted arguments in + the middle: +
+void f(int x = 0, double y = 3.14, std::string z = std::string("foo"));
+
+BOOST_PYTHON_MODULE(test)
+{
+   def("f", f
+       , (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
+}
+ 
+
And in Python: +
+>>> import test
+>>> f(0, z = "bar")
+>>> f(z = "bar", y = 0.0)
+
Thanks, Nikolay! +
+ +
22 July 2003
+ +
Killed the dreaded "bad argument type for builtin operation" error. + Argument errors now show the actual and expected argument types!
+ +
19 July 2003
+ +
Added the new return_arg policy from Nikolay Mladenov. Thanks, Nikolay!
+ +
18 March, 2003
+ +
Gottfried + Ganßauge has contributed opaque pointer support.
+ Bruno da Silva de + Oliveira has contributed the exciting Pyste ("Pie-steh") package.
+ +
24 February 2003
+ +
Finished improved support for boost::shared_ptr. Now any + wrapped object of C++ class X can be converted automatically + to shared_ptr<X>, regardless of how it was wrapped. + The shared_ptr will manage the lifetime of the Python object + which supplied the X, rather than just the X + object itself, and when such a shared_ptr is converted back + to Python, the original Python object will be returned.
+ +
19 January 2003
+ +
Integrated staticmethod support from Nikolay Mladenov. Thanks, Nikolay!
+ +
29 December 2002
+ +
Added Visual Studio project file and instructions from Brett Calcott. + Thanks, Brett!
+ +
20 December 2002
+ +
Added automatic downcasting for pointers, references, and smart + pointers to polymorphic class types upon conversion to python
+ +
18 December 2002
+ +
Optimized from_python conversions for wrapped classes by putting the + conversion logic in the shared library instead of registering separate + converters for each class in each extension module
+ +
19 November 2002
+ +
Removed the need for users to cast base class member function + pointers when used as arguments to add_property
+ +
13 December 2002
+ +
Allow exporting of enum_ values into enclosing + scope.
+ Fixed unsigned integer conversions to deal correctly with numbers that + are out-of-range of signed long.
+ +
14 November 2002
+ +
Auto-detection of class data members wrapped with make_getter
+ +
13 November 2002
+ +
Full Support for std::auto_ptr<> added.
+ +
October 2002
+ +
Ongoing updates and improvements to tutorial documentation
+ +
10 October 2002
+ +
Boost.Python V2 is released!
+
+
+ +

Revised + + 19 November 2004 +

+ +

© Copyright Dave + Abrahams 2002-2003.

+ + diff --git a/libs/python/doc/polymorphism.txt b/libs/python/doc/polymorphism.txt new file mode 100644 index 0000000000..38e2f69145 --- /dev/null +++ b/libs/python/doc/polymorphism.txt @@ -0,0 +1,222 @@ +.. Copyright David Abrahams 2006. 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) + +How Runtime Polymorphism is expressed in Boost.Python: +----------------------------------------------------- + + struct A { virtual std::string f(); virtual ~A(); }; + + std::string call_f(A& x) { return x.f(); } + + struct B { virtual std::string f() { return "B"; } }; + + struct Bcb : B + { + Bcb(PyObject* self) : m_self(self) {} + + virtual std::string f() { return call_method(m_sef, "f"); } + static std::string f_default(B& b) { return b.B::f(); } + + PyObject* m_self; + }; + + struct C : B + { + virtual std::string f() { return "C"; } + }; + + >>> class D(B): + ... def f(): + ... return 'D' + ... + >>> class E(B): pass + ... + + +When we write, "invokes B::f non-virtually", we mean: + + void g(B& x) { x.B::f(); } + +This will call B::f() regardless of the dynamic type of x. Any other +way of invoking B::f, including through a function pointer, is a +"virtual invocation", and will call the most-derived override of f(). + +Case studies + + C++\Python class + \___A_____B_____C_____D____E___ + | + A | 1 + | + B | 2 3 + | + Bcb | 4 5 6 + | + C | 7 8 + | + + +1. Simple case + +2. Python A holds a B*. Probably won't happen once we have forced + downcasting. + + Requires: + x.f() -> 'B' + call_f(x) -> 'B' + + Implies: A.f invokes A::f() (virtually or otherwise) + +3. Python B holds a B*. + + Requires: + x.f() -> 'B' + call_f(x) -> 'B' + + Implies: B.f invokes B::f (virtually or otherwise) + + +4. B constructed from Python + + Requires: + + x.f() -> 'B' + call_f(x) -> 'B' + + Implies: B.f invokes B::f non-virtually. Bcb::f invokes B::f + non-virtually. + + Question: Does it help if we arrange for Python B construction to + build a true B object? Then this case doesn't arise. + + +5. D is a Python class derived from B + + Requires: + + x.f() -> 'D' + call_f(x) -> 'D' + + Implies: Bcb::f must invoke call_method to look up the Python + method override, otherwise call_f wouldn't work. + +6. E is like D, but doesn't override f + + Requires: + + x.f() -> 'B' + call_f(x) -> 'B' + + Implies: B.f invokes B::f non-virtually. If it were virtual, x.f() + would cause infinite recursion, because we've already + determined that Bcb::f must invoke call_method to look up + the Python method override. + +7. Python B object holds a C* + + Requires: + + x.f() -> 'C' + call_f(x) -> 'C' + + Implies: B.f invokes B::f virtually. + +8. C object constructed from Python + + Requires: + + x.f() -> 'C' + call_f(x) -> 'C' + + Implies: nothing new. + +------ + +Total implications: + +2: A.f invokes A::f() (virtually or otherwise) +3: B.f invokes B::f (virtually or otherwise) +4: B.f invokes B::f non-virtually. Bcb::f invokes B::f non-virtually +6: B.f invokes B::f non-virtually. +7: B.f invokes B::f virtually. + +5: Bcb::f invokes call_method to look up the Python method + +Though (4) is avoidable, clearly 6 and 7 are not, and they +conflict. The implication is that B.f must choose its behavior +according to the type of the contained C++ object. If it is Bcb, a +non-virtual call to B::f must occur. Otherwise, a virtual call to B::f +must occur. This is essentially the same scheme we had with +Boost.Python v1. + +Note: in early versions of Boost.Python v1, we solved this problem by +introducing a new Python class in the hierarchy, so that D and E +actually derive from a B', and B'.f invokes B::f non-virtually, while +B.f invokes B::f virtually. However, people complained about the +artificial class in the hierarchy, which was revealed when they tried +to do normal kinds of Python introspection. + +------- + +Assumption: we will have a function which builds a virtual function +dispatch callable Python object. + + make_virtual_function(pvmf, default_impl, call_policies, dispatch_type) + +Pseudocode: + + Get first argument from Python arg tuple + if it contains dispatch_type + call default_impl + else + call through pvmf + + +Open questions: + + 1. What about Python multiple inheritance? Do we have the right + check in the if clause above? + + A: Not quite. The correct test looks like: + + Deduce target type of pvmf, i.e. T in R(T::*)(A1...AN). + Find holder in first argument which holds T + if it holds dispatch_type... + + 2. Can we make this more efficient? + + The current "returning" mechanism will look up a holder for T + again. I don't know if we know how to avoid that. + + + OK, the solution involves reworking the call mechanism. This is + neccesary anyway in order to enable wrapping of function objects. + + It can result in a reduction in the overall amount of source code, + because returning<> won't need to be specialized for every + combination of function and member function... though it will still + need a void specialization. We will still need a way to dispatch to + member functions through a regular function interface. mem_fn is + almost the right tool, but it only goes up to 8 + arguments. Forwarding is tricky if you don't want to incur copies. + I think the trick is to use arg_from_python::result_type for each + argument to the forwarder. + + Another option would be to use separate function, function object, + and member function dispatchers. Once you know you have a member + function, you don't need cv-qualified overloads to call it. + + Hmm, while we're at this, maybe we should solve the write-back + converter problem. Can we do it? Maybe not. Ralf doesn't want to + write special write-back functions here, does he? He wants the + converter to do the work automatically. We could add + cleanup/destructor registration. That would relieve the client from + having accessible destructors for types which are being converted by + rvalue. I'm not sure that this will really save any code, + however. It rather depends on the linker, doesn't it? I wonder if + this can be done in a backwards-compatible fashion by generating the + delete function when it's not supplied? + + diff --git a/libs/python/doc/projects.html b/libs/python/doc/projects.html new file mode 100644 index 0000000000..6a80655c79 --- /dev/null +++ b/libs/python/doc/projects.html @@ -0,0 +1,466 @@ + + + + + + + + + + + + Boost.Python - Projects using Boost.Python + + + + + + + + + +
+

+

+
+

Boost.Python

+ +

Projects using Boost.Python

+
+
+ +

Introduction

+ +

This is a partial list of projects using Boost.Python. If you are using + Boost.Python as your Python/C++ binding solution, we'd be proud to list + your project on this page. Just post a short description of your project + and how Boost.Python helps you get the job done, and we'll add it to this + page .

+
+ +

Data Analysis

+ +
+
NeuraLab
+ +
Neuralab is a data analysis environment specifically tailored for + neural data from Neuralynx + acquisition systems. Neuralab combines presentation quality graphics, a + numerical analysis library, and the Python scripting engine in a single + application. With Neuralab, Neuralynx users can perform common analysis + tasks with just a few mouse clicks. More advanced users can create custom + Python scripts, which can optionally be assigned to menus and mouse + clicks.
+
+ +
+
TSLib - Fortress + Investment Group LLC
+ +
+ Fortress Investment Group has contracted Boost Consulting to develop core + internal financial analysis tools in C++ and to prepare Python bindings + for them using Boost.Python. + +

Tom Barket of Fortress writes:

+ +
+ We have a large C++ analytical library specialized for research in + finance and economics, built for speed and mission critical + stability. Yet Python offers us the flexibility to test out new ideas + quickly and increase the productivity of our time versus working in + C++. There are several key features which make Python stand out. Its + elegance, stability, and breadth of resources on the web are all + valuable, but the most important is its extensibility, due to its + open source transparency. Boost.Python makes Python extensibility + extremely simple and straightforward, yet preserves a great deal of + power and control. +
+
+
+ +

Educational

+ +
+
Kig
+ +
+

KDE Interactive Geometry is a high-school level educational tool, + built for the KDE desktop. It is a nice tool to let students work with + geometrical constructions. It is meant to be the most intuitive, yet + featureful application of its kind.

+ +

Versions after 0.6.x (will) support objects built by the user + himself in the Python language. The exporting of the relevant internal + API's were done using Boost.Python, which made the process very + easy.

+
+
+ +

Enterprise Software

+ +
+
OpenWBEM
+ +
+ The OpenWBEM project is an effort to develop an open-source + implementation of Web Based Enterprise Management suitable for + commercial and non-commercial application + +

Dan Nuffer writes:

+ +
+ I'm using Boost.Python to wrap the client API of OpenWBEM.This will + make it easier to do rapid prototyping, testing, and scripting when + developing management solutions that use WBEM. +
+
+ +
Metafaq
+ +
+ Metafaq, from Transversal, + Inc., is an enterprise level online knowledge base management + system. + +

Ben Young + writes:

+ +
+ Boost.Python is used in an automated process to generate python + bindings to our api which is exposed though multiple backends and + frontends. This allows us to write quick tests and bespoke scripts to + perform one off tasks without having to go through the full + compilation cycle. +
+
+
+ +

Games

+ +
+
Civilization IV
+
+ +
+ “The fourth game in the PC strategy series that has sold over five + million copies, Sid Meier's Civilization IV is a bold step forward for + the franchise, with spectacular new 3D graphics and all-new single and + multiplayer content. Civilization IV will also set a new standard for + user-modification, allowing gamers to create their own add-ons using + Python and XML. + +

Sid Meier's Civilization IV will be released for PC in late 2005. For + more information please visit http://www.firaxis.com or write kgilmore@firaxis.com

+
+ +

Boost.Python is used as the interface layer between the C++ game code + and Python. Python is used for many purposes in the game, including map + generation, interface screens, game events, tools, tutorials, etc. Most + high-level game operations have been exposed to Python in order to give + modders the power they need to customize the game.

+ +
+ -Mustafa Thamer, Civ4 Lead Programmer +
+ +
+
Vega + Strike
+ +
+ Vega Strike is the 3D + Space Simulator that allows you to trade and bounty hunt in a vast + universe. Players face dangers, decisions, piracy, and aliens. + +

Vega Strike has + decided to base its scripting on python, using boost as the layer + between the class hierarchy in python and the class hierarchy in C++. + The result is a very flexible scripting system that treats units as + native python classes when designing missions or writing AI's.

+ +

A large economic and planetary simulation is currently being run in + the background in python and the results are returned back into C++ in + the form of various factions' spaceships appearing near worlds that + they are simulated to be near in python if the player is in the general + neighborhood.

+
+
+ +

Graphics

+ +
+
OpenSceneGraph + Bindings
+ +
Gideon May has created a set + of bindings for OpenSceneGraph, a cross-platform + C++/OpenGL library for the real-time visualization.
+  
+ +
HippoDraw
+ +
+ HippoDraw is a data analysis environment consisting of a canvas upon + which graphs such as histograms, scattter plots, etc, are prsented. It + has a highly interactive GUI interface, but some things you need to do + with scripts. HippoDraw can be run as Python extension module so that + all the manipulation can be done from either Python or the GUI. + +

Before the web page came online, Paul F. Kunz wrote:

+ +
+ Don't have a web page for the project, but the organization's is + http://www.slac.stanford.edu (the + first web server site in America, I installed it). +
Which was just too cool a piece of trivia to omit.
+   +
+ +
IPLT
+ +
+ Ansgar Philippsen + writes: + +
+ IPLT is an image processing library and toolbox for the structural + biology electron microscopy community. I would call it a + budding/evolving project, since it is currently not in production + stage, but rather under heavy development. Python is used as the main + scripting/interaction level, but also for rapid prototyping, since + the underlying C++ class library is pretty much fully exposed via + boost.python (at least the high-level interface). The combined power + of C++ and Python for this project turned out to be just awesome. +

+   +
+ +
PythonMagick
+ +
PythonMagick binds the GraphicsMagick image manipulation + library to Python.
+  
+ +
VPython
+ +
+ Bruce Sherwood writes: + +
+ VPython is an extension for Python that makes it easy to create + navigable 3D animations, which are generated as a side effect of + computational code. VPython is used in education for various + purposes, including teaching physics and programming, but it has also + been used by research scientists to visualize systems or data in 3D. +

+   +
+
+ +

Scientific Computing

+ +
+
CAMFR
+ +
+ CAMFR is a photonics and electromagnetics modelling tool. Python is + used for computational steering. + +

Peter Bienstman + writes:

+ +
+ Thanks for providing such a great tool! +
+
+ +
cctbx - Computational + Crystallography Toolbox
+ +
+ Computational Crystallography is concerned with the derivation of + atomic models of crystal structures, given experimental X-ray + diffraction data. The cctbx is an open-source library of fundamental + algorithms for crystallographic computations. The core algorithms are + implemented in C++ and accessed through higher-level Python interfaces. + +

The cctbx grew together with Boost.Python and is designed from the + ground up as a hybrid Python/C++ system. With one minor exception, + run-time polymorphism is completely handled by Python. C++ compile-time + polymorphism is used to implement performance critical algorithms. The + Python and C++ layers are seamlessly integrated using Boost.Python.

+ +

The SourceForge cctbx project is organized in modules to facilitate + use in non-crystallographic applications. The scitbx module implements + a general purpose array family for scientific applications and pure C++ + ports of FFTPACK and the L-BFGS quasi-Newton minimizer.

+
+ +
EMSolve
+ +
EMSolve is a provably stable, charge conserving, and energy + conserving solver for Maxwell's equations.
+  
+ +
Gaudi and RootPython
+ +
+ Gaudi is a framework for particle physics collision data processing + applications developed in the context of the LHCb and ATLAS experiments + at CERN. + +

Pere Mato Vila writes:

+ +
+ We are using Boost.Python to provide scripting/interactive capability + to our framework. We have a module called "GaudiPython" implemented + using Boost.Python that allows the interaction with any framework + service or algorithm from python. RootPython also uses Boost.Python + to provide a generic "gateway" between the ROOT framework and python + +

Boost.Python is great. We managed very quickly to interface our + framework to python, which is great language. We are trying to + facilitate to our physicists (end-users) a rapid analysis application + development environment based on python. For that, Boost.Python plays + and essential role.

+
+
+ +
ESSS
+ +
+ ESSS (Engineering Simulation and Scientific Software) is a company that + provides engineering solutions and acts in the brazilian and + south-american market providing products and services related to + Computational Fluid Dynamics and Image Analysis. + +

Bruno da Silva de Oliveira + writes:

+ +
+ Recently we moved our work from working exclusively with C++ to an + hybrid-language approach, using Python and C++, with Boost.Python + providing the layer between the two. The results are great so far! +
+ +

Two projects have been developed so far with this technology:

+ +

Simba + provides 3D visualization of geological formations gattered from the + simulation of the evolution of oil systems, allowing the user to + analyse various aspects of the simulation, like deformation, pressure + and fluids, along the time of the simulation.

+ +

Aero aims to + construct a CFD with brazilian technology, which involves various + companies and universities. ESSS is responsible for various of the + application modules, including GUI and post-processing of results.

+
+ +
PolyBoRi
+ +
+

Michael Brickenstein writes:

+ +
+

The core of PolyBoRi is a C++ library, which provides + high-level data types for Boolean polynomials and monomials, + exponent vectors, as well as for the underlying polynomial + rings and subsets of the powerset of the Boolean variables. As + a unique approach, binary decision diagrams are used as + internal storage type for polynomial structures. On top of + this C++-library we provide a Python interface. This allows + parsing of complex polynomial systems, as well as sophisticated + and extendable strategies for Gröbner basis computation. + Boost.Python has helped us to create this interface in a + very clean way.

+
+
+ +
Rational Discovery + LLC
+ +
+ Rational Discovery provides computational modeling, combinatorial + library design and custom software development services to the + pharmaceutical, biotech and chemical industries. We do a substantial + amount of internal research to develop new approaches for applying + machine-learning techniques to solve chemical problems. Because we're a + small organization and chemistry is a large and complex field, it is + essential that we be able to quickly and easily prototype and test new + algorithms. + +

For our internal software, we implement core data structures in C + and expose them to Python using Boost.Python. Algorithm development is + done in Python and then translated to C if required (often it's not). + This hybrid development approach not only greatly increases our + productivity, but it also allows "non-developers" (people without C + experience) to take part in method development. Learning C is a + daunting task, but "Python fits your brain." (Thanks to Bruce Eckel for + the quote.)

+
+
+ +

Systems Libraries

+ +
+
Fusion
+ +
+

Fusion is a library that supports implementing protocols in C++ for + use with Twisted, allowing control over memory allocation strategies, + fast method calls internally, etc.. Fusion supports TCP, UDP and + multicast, and is implemented using the Boost.Python python + bindings.

+ +

Fusion is licensed under the MIT license, and available for download + from http://itamarst.org/software.

+
+
+ +

Tools

+ +
+
Jayacard
+ +
+ Jayacard aims at developing a secure portable open source operating + system for contactless smart cards and a complete suite of high quality + development tools to ease smart card OS and application development. + +

The core of the smart card reader management is written in C++ but + all the development tools are written in the friendly Python language. + Boost plays the fundamental role of binding the tools to our core smart + card reader library.

+
+
+
+ +

Revised + + 29 May, 2008

+ +

© Copyright Dave + Abrahams 2002-2008.

+ + diff --git a/libs/python/doc/support.html b/libs/python/doc/support.html new file mode 100644 index 0000000000..3198563417 --- /dev/null +++ b/libs/python/doc/support.html @@ -0,0 +1,74 @@ + + + + + + + + + + + + Boost.Python - Support Resources + + + + + + + + + +
+

+

+
+

Boost.Python

+ +

Support Resources

+
+
+ +

Synopsis

+ +

This is a list of available resources for support with Boost.Python + problems and feature requests. Please try to resist emailing the + Boost.Python developers directly for support. Use the following + resources instead; the developers are listening!

+
+ +
+
Boost + Consulting - Commercial support, development, training, and + distribution for all the Boost libraries, from the people who brought + you Boost.Python.
+  
+ +
The Python + C++-sig mailing list is a forum for discussing Python/C++ + interoperability, and Boost.Python in particular. Post your + Boost.Python questions here.
+  
+ +
The Boost.Python Wiki + Pages established by Mike Rovner as part of the PythonInfo Wiki serves as + a forum to gather peoples' experience and as a cookbook.
+  
+
+
+ +

Revised + + 12 Sept, 2003 +

+ +

© Copyright Dave + Abrahams 2003.

+ + + diff --git a/libs/python/doc/tutorial/doc/Jamfile.v2 b/libs/python/doc/tutorial/doc/Jamfile.v2 new file mode 100644 index 0000000000..ba8882636d --- /dev/null +++ b/libs/python/doc/tutorial/doc/Jamfile.v2 @@ -0,0 +1,18 @@ +# Copyright Joel de Guzman 2006. 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) +project boost/libs/python/doc/tutorial/doc ; + +import boostbook : boostbook ; +using quickbook ; + +path-constant images : html ; + +boostbook tutorial + : + tutorial.qbk + : + boost.root=../../../../../.. + pdf:img.src.path=$(images)/ + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/python/doc/tutorial/doc/html + ; diff --git a/libs/python/doc/tutorial/doc/html/images/alert.png b/libs/python/doc/tutorial/doc/html/images/alert.png new file mode 100644 index 0000000000..b4645bc7e7 Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/alert.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/home.png b/libs/python/doc/tutorial/doc/html/images/home.png new file mode 100644 index 0000000000..5584aacb09 Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/home.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/jam.png b/libs/python/doc/tutorial/doc/html/images/jam.png new file mode 100644 index 0000000000..224ed7914b Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/jam.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/next.png b/libs/python/doc/tutorial/doc/html/images/next.png new file mode 100644 index 0000000000..59800b4e87 Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/next.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/note.png b/libs/python/doc/tutorial/doc/html/images/note.png new file mode 100644 index 0000000000..3ed047cacb Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/note.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/prev.png b/libs/python/doc/tutorial/doc/html/images/prev.png new file mode 100644 index 0000000000..d88a40f923 Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/prev.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/python.png b/libs/python/doc/tutorial/doc/html/images/python.png new file mode 100644 index 0000000000..cc2ff1d54a Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/python.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/smiley.png b/libs/python/doc/tutorial/doc/html/images/smiley.png new file mode 100644 index 0000000000..30a77f71ce Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/smiley.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/tip.png b/libs/python/doc/tutorial/doc/html/images/tip.png new file mode 100644 index 0000000000..9f596b0b88 Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/tip.png differ diff --git a/libs/python/doc/tutorial/doc/html/images/up.png b/libs/python/doc/tutorial/doc/html/images/up.png new file mode 100644 index 0000000000..17d9c3ec49 Binary files /dev/null and b/libs/python/doc/tutorial/doc/html/images/up.png differ diff --git a/libs/python/doc/tutorial/doc/html/index.html b/libs/python/doc/tutorial/doc/html/index.html new file mode 100644 index 0000000000..c324f065ce --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/index.html @@ -0,0 +1,142 @@ + + + +Chapter 1. python 2.0 + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
Next
+
+
+

+Chapter 1. python 2.0

+

+Joel de Guzman +

+

+David Abrahams +

+
+
+

+ 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 ) +

+
+
+ +
+

+QuickStart

+

+ The Boost Python Library is a framework for interfacing Python and C++. It + allows you to quickly and seamlessly expose C++ classes functions and objects + to Python, and vice-versa, using no special tools -- just your C++ compiler. + It is designed to wrap C++ interfaces non-intrusively, so that you should not + have to change the C++ code at all in order to wrap it, making Boost.Python + ideal for exposing 3rd-party libraries to Python. The library's use of advanced + metaprogramming techniques simplifies its syntax for users, so that wrapping + code takes on the look of a kind of declarative interface definition language + (IDL). +

+

+ + Hello World +

+

+ Following C/C++ tradition, let's start with the "hello, world". A + C++ Function: +

+
char const* greet()
+{
+   return "hello, world";
+}
+
+

+ can be exposed to Python by writing a Boost.Python wrapper: +

+
#include <boost/python.hpp>
+
+BOOST_PYTHON_MODULE(hello_ext)
+{
+    using namespace boost::python;
+    def("greet", greet);
+}
+
+

+ That's it. We're done. We can now build this as a shared library. The resulting + DLL is now visible to Python. Here's a sample Python session: +

+
>>> import hello_ext
+>>> print hello_ext.greet()
+hello, world
+
+

+ Next stop... Building your Hello World module + from start to finish... +

+
+
+ + + +

Last revised: December 26, 2011 at 21:58:39 GMT

+
+
Next
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/embedding.html b/libs/python/doc/tutorial/doc/html/python/embedding.html new file mode 100644 index 0000000000..4e1c21857b --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/embedding.html @@ -0,0 +1,269 @@ + + + +Embedding + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Embedding

+ +

+ By now you should know how to use Boost.Python to call your C++ code from Python. + However, sometimes you may need to do the reverse: call Python code from the + C++-side. This requires you to embed the Python interpreter + into your C++ program. +

+

+ Currently, Boost.Python does not directly support everything you'll need when + embedding. Therefore you'll need to use the Python/C + API to fill in the gaps. However, Boost.Python already makes embedding + a lot easier and, in a future version, it may become unnecessary to touch the + Python/C API at all. So stay tuned... smiley +

+

+ + Building embedded programs +

+

+ To be able to embed python into your programs, you have to link to both Boost.Python's + as well as Python's own runtime library. +

+

+ Boost.Python's library comes in two variants. Both are located in Boost's + /libs/python/build/bin-stage subdirectory. On Windows, the + variants are called boost_python.lib (for release builds) + and boost_python_debug.lib (for debugging). If you can't + find the libraries, you probably haven't built Boost.Python yet. See Building and Testing on how to do this. +

+

+ Python's library can be found in the /libs subdirectory + of your Python directory. On Windows it is called pythonXY.lib where X.Y is + your major Python version number. +

+

+ Additionally, Python's /include subdirectory has to be added + to your include path. +

+

+ In a Jamfile, all the above boils down to: +

+
projectroot c:\projects\embedded_program ; # location of the program
+
+# bring in the rules for python
+SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
+include python.jam ;
+
+exe embedded_program # name of the executable
+  : #sources
+     embedded_program.cpp
+  : # requirements
+     <find-library>boost_python <library-path>c:\boost\libs\python
+  $(PYTHON_PROPERTIES)
+    <library-path>$(PYTHON_LIB_PATH)
+    <find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
+
+

+ + Getting started +

+

+ Being able to build is nice, but there is nothing to build yet. Embedding the + Python interpreter into one of your C++ programs requires these 4 steps: +

+
    +
  1. + #include <boost/python.hpp> +
  2. +
  3. + Call Py_Initialize() + to start the interpreter and create the __main__ module. +
  4. +
  5. + Call other Python C API routines to use the interpreter. +
  6. +
+
+ + + + + +
[Note]Note

+ Note that at this time you must not call Py_Finalize() + to stop the interpreter. This may be fixed in a future version of boost.python. +

+

+ (Of course, there can be other C++ code between all of these steps.) +

+

+ Now that we can embed the interpreter in + our programs, lets see how to put it to use... +

+
+

+Using the interpreter

+

+ As you probably already know, objects in Python are reference-counted. Naturally, + the PyObjects of the Python C API are also reference-counted. + There is a difference however. While the reference-counting is fully automatic + in Python, the Python C API requires you to do it by + hand. This is messy and especially hard to get right in the presence + of C++ exceptions. Fortunately Boost.Python provides the handle + and object class templates to + automate the process. +

+

+ + Running Python code +

+

+ Boost.python provides three related functions to run Python code from C++. +

+
object eval(str expression, object globals = object(), object locals = object())
+object exec(str code, object globals = object(), object locals = object())
+object exec_file(str filename, object globals = object(), object locals = object())
+
+

+ eval evaluates the given expression and returns the resulting value. exec + executes the given code (typically a set of statements) returning the result, + and exec_file executes the code contained in the given file. +

+

+ The globals and locals parameters are + Python dictionaries containing the globals and locals of the context in which + to run the code. For most intents and purposes you can use the namespace + dictionary of the __main__ module for both parameters. +

+

+ Boost.python provides a function to import a module: +

+
object import(str name)
+
+

+ import imports a python module (potentially loading it into the running process + first), and returns it. +

+

+ Let's import the __main__ module and run some Python code + in its namespace: +

+
object main_module = import("__main__");
+object main_namespace = main_module.attr("__dict__");
+
+object ignored = exec("hello = file('hello.txt', 'w')\n"
+                      "hello.write('Hello world!')\n"
+                      "hello.close()",
+                      main_namespace);
+
+

+ This should create a file called 'hello.txt' in the current directory containing + a phrase that is well-known in programming circles. +

+

+ + Manipulating Python objects +

+

+ Often we'd like to have a class to manipulate Python objects. But we have + already seen such a class above, and in the previous + section: the aptly named object class and its + derivatives. We've already seen that they can be constructed from a handle. + The following examples should further illustrate this fact: +

+
object main_module = import("__main__");
+object main_namespace = main_module.attr("__dict__");
+object ignored = exec("result = 5 ** 2", main_namespace);
+int five_squared = extract<int>(main_namespace["result"]);
+
+

+ Here we create a dictionary object for the __main__ module's + namespace. Then we assign 5 squared to the result variable and read this + variable from the dictionary. Another way to achieve the same result is to + use eval instead, which returns the result directly: +

+
object result = eval("5 ** 2");
+int five_squared = extract<int>(result);
+
+

+ + Exception handling +

+

+ If an exception occurs in the evaluation of the python expression, error_already_set + is thrown: +

+
try
+{
+    object result = eval("5/0");
+    // execution will never get here:
+    int five_divided_by_zero = extract<int>(result);
+}
+catch(error_already_set const &)
+{
+    // handle the exception in some way
+}
+
+

+ The error_already_set exception class doesn't carry any + information in itself. To find out more about the Python exception that occurred, + you need to use the exception + handling functions of the Python C API in your catch-statement. This + can be as simple as calling PyErr_Print() + to print the exception's traceback to the console, or comparing the type + of the exception with those of the standard + exceptions: +

+
catch(error_already_set const &)
+{
+    if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
+    {
+        // handle ZeroDivisionError specially
+    }
+    else
+    {
+        // print all other errors to stderr
+        PyErr_Print();
+    }
+}
+
+

+ (To retrieve even more information from the exception you can use some of + the other exception handling functions listed here.) +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/exception.html b/libs/python/doc/tutorial/doc/html/python/exception.html new file mode 100644 index 0000000000..7c053a7e86 --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/exception.html @@ -0,0 +1,63 @@ + + + +Exception Translation + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Exception Translation

+

+ All C++ exceptions must be caught at the boundary with Python code. This boundary + is the point where C++ meets Python. Boost.Python provides a default exception + handler that translates selected standard exceptions, then gives up: +

+
raise RuntimeError, 'unidentifiable C++ Exception'
+
+

+ Users may provide custom translation. Here's an example: +

+
struct PodBayDoorException;
+void translator(PodBayDoorException const& x) {
+    PyErr_SetString(PyExc_UserWarning, "I'm sorry Dave...");
+}
+BOOST_PYTHON_MODULE(kubrick) {
+     register_exception_translator<
+          PodBayDoorException>(translator);
+     ...
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/exposing.html b/libs/python/doc/tutorial/doc/html/python/exposing.html new file mode 100644 index 0000000000..5547b2f205 --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/exposing.html @@ -0,0 +1,591 @@ + + + +Exposing Classes + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Exposing Classes

+ +

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

+

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

+
struct World
+{
+    void set(std::string msg) { this->msg = msg; }
+    std::string greet() { return msg; }
+    std::string msg;
+};
+
+

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

+
#include <boost/python.hpp>
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE(hello)
+{
+    class_<World>("World")
+        .def("greet", &World::greet)
+        .def("set", &World::set)
+    ;
+}
+
+

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

+
>>> import hello
+>>> planet = hello.World()
+>>> planet.set('howdy')
+>>> planet.greet()
+'howdy'
+
+
+

+Constructors

+

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

+
>>> planet = hello.World()
+
+

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

+
struct World
+{
+    World(std::string msg): msg(msg) {} // added constructor
+    void set(std::string msg) { this->msg = msg; }
+    std::string greet() { return msg; }
+    std::string msg;
+};
+
+

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

+
#include <boost/python.hpp>
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE(hello)
+{
+    class_<World>("World", init<std::string>())
+        .def("greet", &World::greet)
+        .def("set", &World::set)
+    ;
+}
+
+

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

+

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

+
class_<World>("World", init<std::string>())
+    .def(init<double, double>())
+    .def("greet", &World::greet)
+    .def("set", &World::set)
+;
+
+

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

+
class_<Abstract>("Abstract", no_init)
+
+

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

+
+
+

+Class Data Members

+

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

+
struct Var
+{
+    Var(std::string name) : name(name), value() {}
+    std::string const name;
+    float value;
+};
+
+

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

+
class_<Var>("Var", init<std::string>())
+    .def_readonly("name", &Var::name)
+    .def_readwrite("value", &Var::value);
+
+

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

+
>>> x = hello.Var('pi')
+>>> x.value = 3.14
+>>> print x.name, 'is around', x.value
+pi is around 3.14
+
+

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

+
>>> x.name = 'e' # can't change name
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+AttributeError: can't set attribute
+
+
+
+

+Class Properties

+

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

+
struct Num
+{
+    Num();
+    float get() const;
+    void set(float value);
+    ...
+};
+
+

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

+
class_<Num>("Num")
+    .add_property("rovalue", &Num::get)
+    .add_property("value", &Num::get, &Num::set);
+
+

+ And at last, in Python: +

+
>>> x = Num()
+>>> x.value = 3.14
+>>> x.value, x.rovalue
+(3.14, 3.14)
+>>> x.rovalue = 2.17 # error!
+
+

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

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

+Inheritance

+

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

+

+ Consider this trivial inheritance structure: +

+
struct Base { virtual ~Base(); };
+struct Derived : Base {};
+
+

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

+
void b(Base*);
+void d(Derived*);
+Base* factory() { return new Derived; }
+
+

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

+
class_<Base>("Base")
+    /*...*/
+    ;
+
+

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

+
class_<Derived, bases<Base> >("Derived")
+    /*...*/
+    ;
+
+

+ Doing so, we get some things for free: +

+
    +
  1. + Derived automatically inherits all of Base's Python methods (wrapped + C++ member functions) +
  2. +
  3. + If Base is polymorphic, Derived + objects which have been passed to Python via a pointer or reference to + Base can be passed where a pointer or reference to + Derived is expected. +
  4. +
+

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

+
def("b", b);
+def("d", d);
+def("factory", factory);
+
+

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

+
// Tell Python to take ownership of factory's result
+def("factory", factory,
+    return_value_policy<manage_new_object>());
+
+
+
+

+Class Virtual Functions

+

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

+
struct Base
+{
+    virtual ~Base() {}
+    virtual int f() = 0;
+};
+
+

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

+
struct BaseWrap : Base, wrapper<Base>
+{
+    int f()
+    {
+        return this->get_override("f")();
+    }
+};
+
+

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

+ +

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

+

+ Finally, exposing Base: +

+
class_<BaseWrap, boost::noncopyable>("Base")
+    .def("f", pure_virtual(&Base::f))
+    ;
+
+

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

+
+ + + + + +
[Note]Note
+

+ member function and methods +

+

+ Python, like many object oriented languages uses the term methods. + Methods correspond roughly to C++'s member functions +

+
+
+
+

+Virtual Functions with Default Implementations

+

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

+

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

+
struct Base
+{
+    virtual int f() = 0;
+};
+
+

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

+
struct Base
+{
+    virtual ~Base() {}
+    virtual int f() { return 0; }
+};
+
+

+ We wrap it this way: +

+
struct BaseWrap : Base, wrapper<Base>
+{
+    int f()
+    {
+        if (override f = this->get_override("f"))
+            return f(); // *note*
+        return Base::f();
+    }
+
+    int default_f() { return this->Base::f(); }
+};
+
+

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

+ +

+ Finally, exposing: +

+
class_<BaseWrap, boost::noncopyable>("Base")
+    .def("f", &Base::f, &BaseWrap::default_f)
+    ;
+
+

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

+

+ In Python, the results would be as expected: +

+
>>> base = Base()
+>>> class Derived(Base):
+...     def f(self):
+...         return 42
+...
+>>> derived = Derived()
+
+

+ Calling base.f(): +

+
>>> base.f()
+0
+
+

+ Calling derived.f(): +

+
>>> derived.f()
+42
+
+
+
+

+Class Operators/Special Functions

+

+ + Python Operators +

+

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

+

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

+
class FilePos { /*...*/ };
+
+FilePos     operator+(FilePos, int);
+FilePos     operator+(int, FilePos);
+int         operator-(FilePos, FilePos);
+FilePos     operator-(FilePos, int);
+FilePos&    operator+=(FilePos&, int);
+FilePos&    operator-=(FilePos&, int);
+bool        operator<(FilePos, FilePos);
+
+

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

+
class_<FilePos>("FilePos")
+    .def(self + int())          // __add__
+    .def(int() + self)          // __radd__
+    .def(self - self)           // __sub__
+    .def(self - int())          // __sub__
+    .def(self += int())         // __iadd__
+    .def(self -= other<int>())
+    .def(self < self);          // __lt__
+
+

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

+

+ + Special Methods +

+

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

+
class Rational
+{ public: operator double() const; };
+
+Rational pow(Rational, Rational);
+Rational abs(Rational);
+ostream& operator<<(ostream&,Rational);
+
+class_<Rational>("Rational")
+    .def(float_(self))                  // __float__
+    .def(pow(self, other<Rational>))    // __pow__
+    .def(abs(self))                     // __abs__
+    .def(str(self))                     // __str__
+    ;
+
+

+ Need we say more? +

+
+ + + + + +
[Note]Note

+ What is the business of operator<<? Well, the method str requires the operator<< to do its work (i.e. operator<< + is used by the method defined by def(str(self)). +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/functions.html b/libs/python/doc/tutorial/doc/html/python/functions.html new file mode 100644 index 0000000000..ca869d1837 --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/functions.html @@ -0,0 +1,586 @@ + + + +Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Functions

+ +

+ In this chapter, we'll look at Boost.Python powered functions in closer detail. + We will see some facilities to make exposing C++ functions to Python safe from + potential pifalls such as dangling pointers and references. We will also see + facilities that will make it even easier for us to expose C++ functions that + take advantage of C++ features such as overloading and default arguments. +

+

+ Read on... +

+

+ But before you do, you might want to fire up Python 2.2 or later and type + >>> import this. +

+
>>> import this
+The Zen of Python, by Tim Peters
+Beautiful is better than ugly.
+Explicit is better than implicit.
+Simple is better than complex.
+Complex is better than complicated.
+Flat is better than nested.
+Sparse is better than dense.
+Readability counts.
+Special cases aren't special enough to break the rules.
+Although practicality beats purity.
+Errors should never pass silently.
+Unless explicitly silenced.
+In the face of ambiguity, refuse the temptation to guess.
+There should be one-- and preferably only one --obvious way to do it
+Although that way may not be obvious at first unless you're Dutch.
+Now is better than never.
+Although never is often better than right now.
+If the implementation is hard to explain, it's a bad idea.
+If the implementation is easy to explain, it may be a good idea.
+Namespaces are one honking great idea -- let's do more of those!
+
+
+

+Call Policies

+

+ In C++, we often deal with arguments and return types such as pointers and + references. Such primitive types are rather, ummmm, low level and they really + don't tell us much. At the very least, we don't know the owner of the pointer + or the referenced object. No wonder languages such as Java and Python never + deal with such low level entities. In C++, it's usually considered a good + practice to use smart pointers which exactly describe ownership semantics. + Still, even good C++ interfaces use raw references and pointers sometimes, + so Boost.Python must deal with them. To do this, it may need your help. Consider + the following C++ function: +

+
X& f(Y& y, Z* z);
+
+

+ How should the library wrap this function? A naive approach builds a Python + X object around result reference. This strategy might or might not work out. + Here's an example where it didn't +

+
>>> x = f(y, z) # x refers to some C++ X
+>>> del y
+>>> x.some_method() # CRASH!
+
+

+ What's the problem? +

+

+ Well, what if f() was implemented as shown below: +

+
X& f(Y& y, Z* z)
+{
+    y.z = z;
+    return y.x;
+}
+
+

+ The problem is that the lifetime of result X& is tied to the lifetime + of y, because the f() returns a reference to a member of the y object. This + idiom is is not uncommon and perfectly acceptable in the context of C++. + However, Python users should not be able to crash the system just by using + our C++ interface. In this case deleting y will invalidate the reference + to X. We have a dangling reference. +

+

+ Here's what's happening: +

+
    +
  1. + f is called passing in a reference to y + and a pointer to z +
  2. +
  3. + A reference to y.x is returned +
  4. +
  5. + y is deleted. x is a dangling reference +
  6. +
  7. + x.some_method() is called +
  8. +
  9. + BOOM! +
  10. +
+

+ We could copy result into a new object: +

+
>>> f(y, z).set(42) # Result disappears
+>>> y.x.get()       # No crash, but still bad
+3.14
+
+

+ This is not really our intent of our C++ interface. We've broken our promise + that the Python interface should reflect the C++ interface as closely as + possible. +

+

+ Our problems do not end there. Suppose Y is implemented as follows: +

+
struct Y
+{
+    X x; Z* z;
+    int z_value() { return z->value(); }
+};
+
+

+ Notice that the data member z is held by class Y using + a raw pointer. Now we have a potential dangling pointer problem inside Y: +

+
>>> x = f(y, z) # y refers to z
+>>> del z       # Kill the z object
+>>> y.z_value() # CRASH!
+
+

+ For reference, here's the implementation of f again: +

+
X& f(Y& y, Z* z)
+{
+    y.z = z;
+    return y.x;
+}
+
+

+ Here's what's happening: +

+
    +
  1. + f is called passing in a reference to y + and a pointer to z +
  2. +
  3. + A pointer to z is held by y +
  4. +
  5. + A reference to y.x is returned +
  6. +
  7. + z is deleted. y.z is a dangling + pointer +
  8. +
  9. + y.z_value() is called +
  10. +
  11. + z->value() is called +
  12. +
  13. + BOOM! +
  14. +
+

+ + Call Policies +

+

+ Call Policies may be used in situations such as the example detailed above. + In our example, return_internal_reference and with_custodian_and_ward + are our friends: +

+
def("f", f,
+    return_internal_reference<1,
+        with_custodian_and_ward<1, 2> >());
+
+

+ What are the 1 and 2 parameters, you + ask? +

+
return_internal_reference<1
+
+

+ Informs Boost.Python that the first argument, in our case Y& + y, is the owner of the returned reference: X&. + The "1" simply specifies the first argument. + In short: "return an internal reference X& owned + by the 1st argument Y& y". +

+
with_custodian_and_ward<1, 2>
+
+

+ Informs Boost.Python that the lifetime of the argument indicated by ward + (i.e. the 2nd argument: Z* z) is dependent on the lifetime + of the argument indicated by custodian (i.e. the 1st argument: Y& + y). +

+

+ It is also important to note that we have defined two policies above. Two + or more policies can be composed by chaining. Here's the general syntax: +

+
policy1<args...,
+    policy2<args...,
+        policy3<args...> > >
+
+

+ Here is the list of predefined call policies. A complete reference detailing + these can be found here. +

+
    +
  • + with_custodian_and_ward: Ties lifetimes + of the arguments +
  • +
  • + with_custodian_and_ward_postcall: Ties + lifetimes of the arguments and results +
  • +
  • + return_internal_reference: Ties lifetime + of one argument to that of result +
  • +
  • + return_value_policy<T> with T one of: +
      +
    • + reference_existing_object: naive + (dangerous) approach +
    • +
    • + copy_const_reference: Boost.Python + v1 approach +
    • +
    • + copy_non_const_reference: +
    • +
    • + manage_new_object: Adopt a pointer + and hold the instance +
    • +
    +
  • +
+ +
+
+

+Overloading

+

+ The following illustrates a scheme for manually wrapping an overloaded member + functions. Of course, the same technique can be applied to wrapping overloaded + non-member functions. +

+

+ We have here our C++ class: +

+
struct X
+{
+    bool f(int a)
+    {
+        return true;
+    }
+
+    bool f(int a, double b)
+    {
+        return true;
+    }
+
+    bool f(int a, double b, char c)
+    {
+        return true;
+    }
+
+    int f(int a, int b, int c)
+    {
+        return a + b + c;
+    };
+};
+
+

+ Class X has 4 overloaded functions. We will start by introducing some member + function pointer variables: +

+
bool    (X::*fx1)(int)              = &X::f;
+bool    (X::*fx2)(int, double)      = &X::f;
+bool    (X::*fx3)(int, double, char)= &X::f;
+int     (X::*fx4)(int, int, int)    = &X::f;
+
+

+ With these in hand, we can proceed to define and wrap this for Python: +

+
.def("f", fx1)
+.def("f", fx2)
+.def("f", fx3)
+.def("f", fx4)
+
+
+
+

+Default Arguments

+

+ Boost.Python wraps (member) function pointers. Unfortunately, C++ function + pointers carry no default argument info. Take a function f + with default arguments: +

+
int f(int, double = 3.14, char const* = "hello");
+
+

+ But the type of a pointer to the function f has no information + about its default arguments: +

+
int(*g)(int,double,char const*) = f;    // defaults lost!
+
+

+ When we pass this function pointer to the def function, + there is no way to retrieve the default arguments: +

+
def("f", f);                            // defaults lost!
+
+

+ Because of this, when wrapping C++ code, we had to resort to manual wrapping + as outlined in the previous section, + or writing thin wrappers: +

+
// write "thin wrappers"
+int f1(int x) { f(x); }
+int f2(int x, double y) { f(x,y); }
+
+/*...*/
+
+    // in module init
+    def("f", f);  // all arguments
+    def("f", f2); // two arguments
+    def("f", f1); // one argument
+
+

+ When you want to wrap functions (or member functions) that either: +

+
    +
  • + have default arguments, or +
  • +
  • + are overloaded with a common sequence of initial arguments +
  • +
+

+ + BOOST_PYTHON_FUNCTION_OVERLOADS +

+

+ Boost.Python now has a way to make it easier. For instance, given a function: +

+
int foo(int a, char b = 1, unsigned c = 2, double d = 3)
+{
+    /*...*/
+}
+
+

+ The macro invocation: +

+
BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)
+
+

+ will automatically create the thin wrappers for us. This macro will create + a class foo_overloads that can be passed on to def(...). + The third and fourth macro argument are the minimum arguments and maximum + arguments, respectively. In our foo function the minimum + number of arguments is 1 and the maximum number of arguments is 4. The def(...) + function will automatically add all the foo variants for us: +

+
def("foo", foo, foo_overloads());
+
+

+ + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS +

+

+ Objects here, objects there, objects here there everywhere. More frequently + than anything else, we need to expose member functions of our classes to + Python. Then again, we have the same inconveniences as before when default + arguments or overloads with a common sequence of initial arguments come into + play. Another macro is provided to make this a breeze. +

+

+ Like BOOST_PYTHON_FUNCTION_OVERLOADS, BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + may be used to automatically create the thin wrappers for wrapping member + functions. Let's have an example: +

+
struct george
+{
+    void
+    wack_em(int a, int b = 0, char c = 'x')
+    {
+        /*...*/
+    }
+};
+
+

+ The macro invocation: +

+
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
+
+

+ will generate a set of thin wrappers for george's wack_em + member function accepting a minimum of 1 and a maximum of 3 arguments (i.e. + the third and fourth macro argument). The thin wrappers are all enclosed + in a class named george_overloads that can then be used + as an argument to def(...): +

+
.def("wack_em", &george::wack_em, george_overloads());
+
+

+ See the overloads + reference for details. +

+

+ + init and optional +

+

+ A similar facility is provided for class constructors, again, with default + arguments or a sequence of overloads. Remember init<...>? + For example, given a class X with a constructor: +

+
struct X
+{
+    X(int a, char b = 'D', std::string c = "constructor", double d = 0.0);
+    /*...*/
+}
+
+

+ You can easily add this constructor to Boost.Python in one shot: +

+
.def(init<int, optional<char, std::string, double> >())
+
+

+ Notice the use of init<...> and optional<...> + to signify the default (optional arguments). +

+
+
+

+Auto-Overloading

+

+ It was mentioned in passing in the previous section that BOOST_PYTHON_FUNCTION_OVERLOADS + and BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS can also be + used for overloaded functions and member functions with a common sequence + of initial arguments. Here is an example: +

+
void foo()
+{
+   /*...*/
+}
+
+void foo(bool a)
+{
+   /*...*/
+}
+
+void foo(bool a, int b)
+{
+   /*...*/
+}
+
+void foo(bool a, int b, char c)
+{
+   /*...*/
+}
+
+

+ Like in the previous section, we can generate thin wrappers for these overloaded + functions in one-shot: +

+
BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
+
+

+ Then... +

+
.def("foo", (void(*)(bool, int, char))0, foo_overloads());
+
+

+ Notice though that we have a situation now where we have a minimum of zero + (0) arguments and a maximum of 3 arguments. +

+

+ + Manual Wrapping +

+

+ It is important to emphasize however that the overloaded + functions must have a common sequence of initial arguments. Otherwise, + our scheme above will not work. If this is not the case, we have to wrap + our functions manually. +

+

+ Actually, we can mix and match manual wrapping of overloaded functions and + automatic wrapping through BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + and its sister, BOOST_PYTHON_FUNCTION_OVERLOADS. Following + up on our example presented in the section on + overloading, since the first 4 overload functins have a common sequence + of initial arguments, we can use BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + to automatically wrap the first three of the defs and + manually wrap just the last. Here's how we'll do this: +

+
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
+
+

+ Create a member function pointers as above for both X::f overloads: +

+
bool    (X::*fx1)(int, double, char)    = &X::f;
+int     (X::*fx2)(int, int, int)        = &X::f;
+
+

+ Then... +

+
.def("f", fx1, xf_overloads());
+.def("f", fx2)
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/hello.html b/libs/python/doc/tutorial/doc/html/python/hello.html new file mode 100644 index 0000000000..b78573826d --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/hello.html @@ -0,0 +1,195 @@ + + + +Building Hello World + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Building Hello World

+

+ + From Start To Finish +

+

+ Now the first thing you'd want to do is to build the Hello World module and + try it for yourself in Python. In this section, we will outline the steps necessary + to achieve that. We will use the build tool that comes bundled with every boost + distribution: bjam. +

+
+ + + + + +
[Note]Note
+

+ Building without bjam +

+

+ Besides bjam, there are of course other ways to get your module built. What's + written here should not be taken as "the one and only way". There + are of course other build tools apart from bjam. +

+

+ Take note however that the preferred build tool for Boost.Python is bjam. + There are so many ways to set up the build incorrectly. Experience shows + that 90% of the "I can't build Boost.Python" problems come from + people who had to use a different tool. +

+
+

+ We will skip over the details. Our objective will be to simply create the hello + world module and run it in Python. For a complete reference to building Boost.Python, + check out: building.html. After + this brief bjam tutorial, we should have built the DLLs + and run a python program using the extension. +

+

+ The tutorial example can be found in the directory: libs/python/example/tutorial. + There, you can find: +

+
    +
  • + hello.cpp +
  • +
  • + hello.py +
  • +
  • + Jamroot +
  • +
+

+ The hello.cpp file is our C++ hello world example. The + Jamroot is a minimalist bjam script + that builds the DLLs for us. Finally, hello.py is our Python + program that uses the extension in hello.cpp. +

+

+ Before anything else, you should have the bjam executable in your boost directory + or somewhere in your path such that bjam can be executed + in the command line. Pre-built Boost.Jam executables are available for most + platforms. The complete list of Bjam executables can be found here. +

+

+ + Let's Jam! +

+

+ jam +

+

+ Here is our minimalist + Jamroot file. Simply copy the file and tweak use-project boost + to where your boost root directory is and your OK. +

+

+ The comments contained in the Jamrules file above should be sufficient to get + you going. +

+

+ + Running bjam +

+

+ bjam is run using your operating system's command line + interpreter. +

+

+ Start it up. +

+

+ A file called user-config.jam in your home directory is used to configure your + tools. In Windows, your home directory can be found by typing: +

+
ECHO %HOMEDRIVE%%HOMEPATH%
+
+

+ into a command prompt window. Your file should at least have the rules for + your compiler and your python installation. A specific example of this on Windows + would be: +

+
#  MSVC configuration
+using msvc : 8.0 ;
+
+#  Python configuration
+using python : 2.4 : C:dev/tools/Python ;
+
+

+ The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools. + The second rule provides information on Python, its version and where it is + located. The above assumes that the Python installation is in C:dev/tools\/Python. + If you have one fairly "standard" python installation for your platform, + you might not need to do this. +

+

+ Now we are ready... Be sure to cd to libs/python/example/tutorial + where the tutorial "hello.cpp" and the "Jamroot" + is situated. +

+

+ Finally: +

+
bjam
+
+

+ It should be building now: +

+
cd C:\dev\boost\libs\python\example\tutorial
+bjam
+...patience...
+...found 1101 targets...
+...updating 35 targets...
+
+

+ And so on... Finally: +

+
Creating library path-to-boost_python.dll
+   Creating library /path-to-hello_ext.exp/
+**passed** ... hello.test
+...updated 35 targets...
+
+

+ Or something similar. If all is well, you should now have built the DLLs and + run the Python program. +

+

+ There you go... Have fun! +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/iterators.html b/libs/python/doc/tutorial/doc/html/python/iterators.html new file mode 100644 index 0000000000..9fb402b6b5 --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/iterators.html @@ -0,0 +1,187 @@ + + + +Iterators + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Iterators

+

+ In C++, and STL in particular, we see iterators everywhere. Python also has + iterators, but these are two very different beasts. +

+

+ C++ iterators: +

+
    +
  • + C++ has 5 type categories (random-access, bidirectional, forward, input, + output) +
  • +
  • + There are 2 Operation categories: reposition, access +
  • +
  • + A pair of iterators is needed to represent a (first/last) range. +
  • +
+

+ Python Iterators: +

+
    +
  • + 1 category (forward) +
  • +
  • + 1 operation category (next()) +
  • +
  • + Raises StopIteration exception at end +
  • +
+

+ The typical Python iteration protocol: for y + in x... is as follows: +

+
iter = x.__iter__()         # get iterator
+try:
+    while 1:
+    y = iter.next()         # get each item
+    ...                     # process y
+except StopIteration: pass  # iterator exhausted
+
+

+ Boost.Python provides some mechanisms to make C++ iterators play along nicely + as Python iterators. What we need to do is to produce appropriate __iter__ function from C++ iterators that + is compatible with the Python iteration protocol. For example: +

+
object get_iterator = iterator<vector<int> >();
+object iter = get_iterator(v);
+object first = iter.next();
+
+

+ Or for use in class_<>: +

+
.def("__iter__", iterator<vector<int> >())
+
+

+ range +

+

+ We can create a Python savvy iterator using the range function: +

+
    +
  • + range(start, finish) +
  • +
  • + range<Policies,Target>(start, finish) +
  • +
+

+ Here, start/finish may be one of: +

+
    +
  • + member data pointers +
  • +
  • + member function pointers +
  • +
  • + adaptable function object (use Target parameter) +
  • +
+

+ iterator +

+
  • + iterator<T, Policies>() +
+

+ Given a container T, iterator is a shortcut that simply + calls range with &T::begin, &T::end. +

+

+ Let's put this into action... Here's an example from some hypothetical bogon + Particle accelerator code: +

+
f = Field()
+for x in f.pions:
+    smash(x)
+for y in f.bogons:
+    count(y)
+
+

+ Now, our C++ Wrapper: +

+
class_<F>("Field")
+    .property("pions", range(&F::p_begin, &F::p_end))
+    .property("bogons", range(&F::b_begin, &F::b_end));
+
+

+ stl_input_iterator +

+

+ So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes + we wish to go the other way, though: we'd like to pass a Python sequence to + an STL algorithm or use it to initialize an STL container. We need to make + a Python iterator look like an STL iterator. For that, we use stl_input_iterator<>. + Consider how we might implement a function that exposes std::list<int>::assign() to Python: +

+
template<typename T>
+void list_assign(std::list<T>& l, object o) {
+    // Turn a Python sequence into an STL input range
+    stl_input_iterator<T> begin(o), end;
+    l.assign(begin, end);
+}
+
+// Part of the wrapper for list<int>
+class_<std::list<int> >("list_int")
+    .def("assign", &list_assign<int>)
+    // ...
+    ;
+
+

+ Now in Python, we can assign any integer sequence to list_int + objects: +

+
x = list_int();
+x.assign([1,2,3,4,5])
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/object.html b/libs/python/doc/tutorial/doc/html/python/object.html new file mode 100644 index 0000000000..7bc2aa255d --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/object.html @@ -0,0 +1,360 @@ + + + +Object Interface + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Object Interface

+ +

+ Python is dynamically typed, unlike C++ which is statically typed. Python variables + may hold an integer, a float, list, dict, tuple, str, long etc., among other + things. In the viewpoint of Boost.Python and C++, these Pythonic variables + are just instances of class object. We will see in this + chapter how to deal with Python objects. +

+

+ As mentioned, one of the goals of Boost.Python is to provide a bidirectional + mapping between C++ and Python while maintaining the Python feel. Boost.Python + C++ objects are as close as possible to Python. This should + minimize the learning curve significantly. +

+

+ python +

+
+

+Basic Interface

+

+ Class object wraps PyObject*. All the + intricacies of dealing with PyObjects such as managing + reference counting are handled by the object class. C++ + object interoperability is seamless. Boost.Python C++ objects + can in fact be explicitly constructed from any C++ object. +

+

+ To illustrate, this Python code snippet: +

+
def f(x, y):
+     if (y == 'foo'):
+         x[3:7] = 'bar'
+     else:
+         x.items += y(3, x)
+     return x
+
+def getfunc():
+   return f;
+
+

+ Can be rewritten in C++ using Boost.Python facilities this way: +

+
object f(object x, object y) {
+     if (y == "foo")
+         x.slice(3,7) = "bar";
+     else
+         x.attr("items") += y(3, x);
+     return x;
+}
+object getfunc() {
+    return object(f);
+}
+
+

+ Apart from cosmetic differences due to the fact that we are writing the code + in C++, the look and feel should be immediately apparent to the Python coder. +

+
+
+

+Derived Object types

+

+ Boost.Python comes with a set of derived object types + corresponding to that of Python's: +

+
    +
  • + list +
  • +
  • + dict +
  • +
  • + tuple +
  • +
  • + str +
  • +
  • + long_ +
  • +
  • + enum +
  • +
+

+ These derived object types act like real Python types. + For instance: +

+
str(1) ==> "1"
+
+

+ Wherever appropriate, a particular derived object has + corresponding Python type's methods. For instance, dict + has a keys() method: +

+
d.keys()
+
+

+ make_tuple is provided for declaring tuple literals. + Example: +

+
make_tuple(123, 'D', "Hello, World", 0.0);
+
+

+ In C++, when Boost.Python objects are used as arguments + to functions, subtype matching is required. For example, when a function + f, as declared below, is wrapped, it will only accept + instances of Python's str type and subtypes. +

+
void f(str name)
+{
+    object n2 = name.attr("upper")();   // NAME = name.upper()
+    str NAME = name.upper();            // better
+    object msg = "%s is bigger than %s" % make_tuple(NAME,name);
+}
+
+

+ In finer detail: +

+
str NAME = name.upper();
+
+

+ Illustrates that we provide versions of the str type's methods as C++ member + functions. +

+
object msg = "%s is bigger than %s" % make_tuple(NAME,name);
+
+

+ Demonstrates that you can write the C++ equivalent of "format" + % x,y,z in Python, which is useful since there's no easy way to + do that in std C++. +

+ +

+ Python: +

+
>>> d = dict(x.__dict__)     # copies x.__dict__
+>>> d['whatever'] = 3        # modifies the copy
+
+

+ C++: +

+
dict d(x.attr("__dict__"));  // copies x.__dict__
+d['whatever'] = 3;           // modifies the copy
+
+

+ + class_<T> as objects +

+

+ Due to the dynamic nature of Boost.Python objects, any class_<T> + may also be one of these types! The following code snippet wraps the class + (type) object. +

+

+ We can use this to create wrapped instances. Example: +

+
object vec345 = (
+    class_<Vec2>("Vec2", init<double, double>())
+        .def_readonly("length", &Point::length)
+        .def_readonly("angle", &Point::angle)
+    )(3.0, 4.0);
+
+assert(vec345.attr("length") == 5.0);
+
+
+
+

+Extracting C++ objects

+

+ At some point, we will need to get C++ values out of object instances. This + can be achieved with the extract<T> function. Consider + the following: +

+
double x = o.attr("length"); // compile error
+
+

+ In the code above, we got a compiler error because Boost.Python object + can't be implicitly converted to doubles. Instead, what + we wanted to do above can be achieved by writing: +

+
double l = extract<double>(o.attr("length"));
+Vec2& v = extract<Vec2&>(o);
+assert(l == v.length());
+
+

+ The first line attempts to extract the "length" attribute of the + Boost.Python object. The second line attempts to extract + the Vec2 object from held by the Boost.Python object. +

+

+ Take note that we said "attempt to" above. What if the Boost.Python + object does not really hold a Vec2 + type? This is certainly a possibility considering the dynamic nature of Python + objects. To be on the safe side, if the C++ type can't + be extracted, an appropriate exception is thrown. To avoid an exception, + we need to test for extractibility: +

+
extract<Vec2&> x(o);
+if (x.check()) {
+    Vec2& v = x(); ...
+
+

+ tip The astute reader might have noticed that the extract<T> + facility in fact solves the mutable copying problem: +

+
dict d = extract<dict>(x.attr("__dict__"));
+d["whatever"] = 3;          // modifies x.__dict__ !
+
+
+
+

+Enums

+

+ Boost.Python has a nifty facility to capture and wrap C++ enums. While Python + has no enum type, we'll often want to expose our C++ enums + to Python as an int. Boost.Python's enum facility makes + this easy while taking care of the proper conversions from Python's dynamic + typing to C++'s strong static typing (in C++, ints cannot be implicitly converted + to enums). To illustrate, given a C++ enum: +

+
enum choice { red, blue };
+
+

+ the construct: +

+
enum_<choice>("choice")
+    .value("red", red)
+    .value("blue", blue)
+    ;
+
+

+ can be used to expose to Python. The new enum type is created in the current + scope(), which is usually the current module. The snippet + above creates a Python class derived from Python's int + type which is associated with the C++ type passed as its first parameter. +

+
+ + + + + +
[Note]Note
+

+ what is a scope? +

+

+ The scope is a class that has an associated global Python object which + controls the Python namespace in which new extension classes and wrapped + functions will be defined as attributes. Details can be found here. +

+
+

+ You can access those values in Python as +

+
>>> my_module.choice.red
+my_module.choice.red
+
+

+ where my_module is the module where the enum is declared. You can also create + a new scope around a class: +

+
scope in_X = class_<X>("X")
+                .def( ... )
+                .def( ... )
+            ;
+
+// Expose X::nested as X.nested
+enum_<X::nested>("nested")
+    .value("red", red)
+    .value("blue", blue)
+    ;
+
+
+
+

+Creating boost::python::object from PyObject* +

+

+ When you want a boost::python::object to manage a pointer to PyObject* + pyobj one does: +

+
boost::python::object o(boost::python::handle<>(pyobj));
+
+

+ In this case, the o object, + manages the pyobj, it won’t + increase the reference count on construction. +

+

+ Otherwise, to use a borrowed reference: +

+
boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj)));
+
+

+ In this case, Py_INCREF is + called, so pyobj is not destructed + when object o goes out of scope. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/python/doc/tutorial/doc/html/python/techniques.html b/libs/python/doc/tutorial/doc/html/python/techniques.html new file mode 100644 index 0000000000..34cfc44426 --- /dev/null +++ b/libs/python/doc/tutorial/doc/html/python/techniques.html @@ -0,0 +1,440 @@ + + + +General Techniques + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHome +
+
+

+General Techniques

+ +

+ Here are presented some useful techniques that you can use while wrapping code + with Boost.Python. +

+
+

+Creating Packages

+

+ A Python package is a collection of modules that provide to the user a certain + functionality. If you're not familiar on how to create packages, a good introduction + to them is provided in the Python + Tutorial. +

+

+ But we are wrapping C++ code, using Boost.Python. How can we provide a nice + package interface to our users? To better explain some concepts, let's work + with an example. +

+

+ We have a C++ library that works with sounds: reading and writing various + formats, applying filters to the sound data, etc. It is named (conveniently) + sounds. Our library already has a neat C++ namespace hierarchy, + like so: +

+
sounds::core
+sounds::io
+sounds::filters
+
+

+ We would like to present this same hierarchy to the Python user, allowing + him to write code like this: +

+
import sounds.filters
+sounds.filters.echo(...) # echo is a C++ function
+
+

+ The first step is to write the wrapping code. We have to export each module + separately with Boost.Python, like this: +

+
/* file core.cpp */
+BOOST_PYTHON_MODULE(core)
+{
+    /* export everything in the sounds::core namespace */
+    ...
+}
+
+/* file io.cpp */
+BOOST_PYTHON_MODULE(io)
+{
+    /* export everything in the sounds::io namespace */
+    ...
+}
+
+/* file filters.cpp */
+BOOST_PYTHON_MODULE(filters)
+{
+    /* export everything in the sounds::filters namespace */
+    ...
+}
+
+

+ Compiling these files will generate the following Python extensions: core.pyd, + io.pyd and filters.pyd. +

+
+ + + + + +
[Note]Note

+ The extension .pyd is used for python extension modules, + which are just shared libraries. Using the default for your system, like + .so for Unix and .dll for Windows, + works just as well. +

+

+ Now, we create this directory structure for our Python package: +

+
sounds/
+    __init__.py
+    core.pyd
+    filters.pyd
+    io.pyd
+
+

+ The file __init__.py is what tells Python that the directory + sounds/ is actually a Python package. It can be a empty + file, but can also perform some magic, that will be shown later. +

+

+ Now our package is ready. All the user has to do is put sounds + into his PYTHONPATH + and fire up the interpreter: +

+
>>> import sounds.io
+>>> import sounds.filters
+>>> sound = sounds.io.open('file.mp3')
+>>> new_sound = sounds.filters.echo(sound, 1.0)
+
+

+ Nice heh? +

+

+ This is the simplest way to create hierarchies of packages, but it is not + very flexible. What if we want to add a pure Python + function to the filters package, for instance, one that applies 3 filters + in a sound object at once? Sure, you can do this in C++ and export it, but + why not do so in Python? You don't have to recompile the extension modules, + plus it will be easier to write it. +

+

+ If we want this flexibility, we will have to complicate our package hierarchy + a little. First, we will have to change the name of the extension modules: +

+
/* file core.cpp */
+BOOST_PYTHON_MODULE(_core)
+{
+    ...
+    /* export everything in the sounds::core namespace */
+}
+
+

+ Note that we added an underscore to the module name. The filename will have + to be changed to _core.pyd as well, and we do the same + to the other extension modules. Now, we change our package hierarchy like + so: +

+
sounds/
+    __init__.py
+    core/
+        __init__.py
+        core.pyd
+    filters/
+        \_init__.py
+        filters.pyd
+    io/
+        \_init__.py
+        _io.pyd
+
+

+ Note that we created a directory for each extension module, and added a __init__.py + to each one. But if we leave it that way, the user will have to access the + functions in the core module with this syntax: +

+
>>> import sounds.core._core
+>>> sounds.core._core.foo(...)
+
+

+ which is not what we want. But here enters the __init__.py + magic: everything that is brought to the __init__.py namespace + can be accessed directly by the user. So, all we have to do is bring the + entire namespace from _core.pyd to core/__init__.py. + So add this line of code to sounds/core/__init__.py: +

+
from _core import *
+
+

+ We do the same for the other packages. Now the user accesses the functions + and classes in the extension modules like before: +

+
>>> import sounds.filters
+>>> sounds.filters.echo(...)
+
+

+ with the additional benefit that we can easily add pure Python functions + to any module, in a way that the user can't tell the difference between a + C++ function and a Python function. Let's add a pure + Python function, echo_noise, to the filters + package. This function applies both the echo and noise + filters in sequence in the given sound object. We create + a file named sounds/filters/echo_noise.py and code our + function: +

+
import _filters
+def echo_noise(sound):
+    s = _filters.echo(sound)
+    s = _filters.noise(sound)
+    return s
+
+

+ Next, we add this line to sounds/filters/__init__.py: +

+
from echo_noise import echo_noise
+
+

+ And that's it. The user now accesses this function like any other function + from the filters package: +

+
>>> import sounds.filters
+>>> sounds.filters.echo_noise(...)
+
+
+
+

+Extending Wrapped Objects in Python

+

+ Thanks to Python's flexibility, you can easily add new methods to a class, + even after it was already created: +

+
>>> class C(object): pass
+>>>
+>>> # a regular function
+>>> def C_str(self): return 'A C instance!'
+>>>
+>>> # now we turn it in a member function
+>>> C.__str__ = C_str
+>>>
+>>> c = C()
+>>> print c
+A C instance!
+>>> C_str(c)
+A C instance!
+
+

+ Yes, Python rox. smiley +

+

+ We can do the same with classes that were wrapped with Boost.Python. Suppose + we have a class point in C++: +

+
class point {...};
+
+BOOST_PYTHON_MODULE(_geom)
+{
+    class_<point>("point")...;
+}
+
+

+ If we are using the technique from the previous session, Creating + Packages, we can code directly into geom/__init__.py: +

+
from _geom import *
+
+# a regular function
+def point_str(self):
+    return str((self.x, self.y))
+
+# now we turn it into a member function
+point.__str__ = point_str
+
+

+ All point instances created from C++ will + also have this member function! This technique has several advantages: +

+
    +
  • + Cut down compile times to zero for these additional functions +
  • +
  • + Reduce the memory footprint to virtually zero +
  • +
  • + Minimize the need to recompile +
  • +
  • + Rapid prototyping (you can move the code to C++ if required without changing + the interface) +
  • +
+

+ You can even add a little syntactic sugar with the use of metaclasses. Let's + create a special metaclass that "injects" methods in other classes. +

+
# The one Boost.Python uses for all wrapped classes.
+# You can use here any class exported by Boost instead of "point"
+BoostPythonMetaclass = point.__class__
+
+class injector(object):
+    class __metaclass__(BoostPythonMetaclass):
+        def __init__(self, name, bases, dict):
+            for b in bases:
+                if type(b) not in (self, type):
+                    for k,v in dict.items():
+                        setattr(b,k,v)
+            return type.__init__(self, name, bases, dict)
+
+# inject some methods in the point foo
+class more_point(injector, point):
+    def __repr__(self):
+        return 'Point(x=%s, y=%s)' % (self.x, self.y)
+    def foo(self):
+        print 'foo!'
+
+

+ Now let's see how it got: +

+
>>> print point()
+Point(x=10, y=10)
+>>> point().foo()
+foo!
+
+

+ Another useful idea is to replace constructors with factory functions: +

+
_point = point
+
+def point(x=0, y=0):
+    return _point(x, y)
+
+

+ In this simple case there is not much gained, but for constructurs with many + overloads and/or arguments this is often a great simplification, again with + virtually zero memory footprint and zero compile-time overhead for the keyword + support. +

+
+
+

+Reducing Compiling Time

+

+ If you have ever exported a lot of classes, you know that it takes quite + a good time to compile the Boost.Python wrappers. Plus the memory consumption + can easily become too high. If this is causing you problems, you can split + the class_ definitions in multiple files: +

+
/* file point.cpp */
+#include <point.h>
+#include <boost/python.hpp>
+
+void export_point()
+{
+    class_<point>("point")...;
+}
+
+/* file triangle.cpp */
+#include <triangle.h>
+#include <boost/python.hpp>
+
+void export_triangle()
+{
+    class_<triangle>("triangle")...;
+}
+
+

+ Now you create a file main.cpp, which contains the BOOST_PYTHON_MODULE + macro, and call the various export functions inside it. +

+
void export_point();
+void export_triangle();
+
+BOOST_PYTHON_MODULE(_geom)
+{
+    export_point();
+    export_triangle();
+}
+
+

+ Compiling and linking together all this files produces the same result as + the usual approach: +

+
#include <boost/python.hpp>
+#include <point.h>
+#include <triangle.h>
+
+BOOST_PYTHON_MODULE(_geom)
+{
+    class_<point>("point")...;
+    class_<triangle>("triangle")...;
+}
+
+

+ but the memory is kept under control. +

+

+ This method is recommended too if you are developing the C++ library and + exporting it to Python at the same time: changes in a class will only demand + the compilation of a single cpp, instead of the entire wrapper code. +

+
+ + + + + +
[Note]Note

+ If you're exporting your classes with Pyste, + take a look at the --multiple option, that generates + the wrappers in various files as demonstrated here. +

+
+ + + + + +
[Note]Note

+ This method is useful too if you are getting the error message "fatal + error C1204:Compiler limit:internal structure overflow" + when compiling a large source file, as explained in the FAQ. +

+
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/libs/python/doc/tutorial/doc/tutorial.qbk b/libs/python/doc/tutorial/doc/tutorial.qbk new file mode 100644 index 0000000000..204c500449 --- /dev/null +++ b/libs/python/doc/tutorial/doc/tutorial.qbk @@ -0,0 +1,1985 @@ +[library python + [version 2.0] + [authors [de Guzman, Joel], [Abrahams, David]] + [copyright 2002 2003 2004 2005 Joel de Guzman, David Abrahams] + [category inter-language support] + [purpose + Reflects C++ classes and functions into Python + ] + [license + 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 + ) + ] +] + +[/ QuickBook Document version 0.9 ] + +[def __note__ [$images/note.png]] +[def __alert__ [$images/alert.png]] +[def __tip__ [$images/tip.png]] +[def :-) [$images/smiley.png]] +[def __jam__ [$images/jam.png]] + +[section QuickStart] + +The Boost Python Library is a framework for interfacing Python and +C++. It allows you to quickly and seamlessly expose C++ classes +functions and objects to Python, and vice-versa, using no special +tools -- just your C++ compiler. It is designed to wrap C++ interfaces +non-intrusively, so that you should not have to change the C++ code at +all in order to wrap it, making Boost.Python ideal for exposing +3rd-party libraries to Python. The library's use of advanced +metaprogramming techniques simplifies its syntax for users, so that +wrapping code takes on the look of a kind of declarative interface +definition language (IDL). + +[h2 Hello World] + +Following C/C++ tradition, let's start with the "hello, world". A C++ +Function: + + char const* greet() + { + return "hello, world"; + } + +can be exposed to Python by writing a Boost.Python wrapper: + + #include + + BOOST_PYTHON_MODULE(hello_ext) + { + using namespace boost::python; + def("greet", greet); + } + +That's it. We're done. We can now build this as a shared library. The +resulting DLL is now visible to Python. Here's a sample Python session: + +[python] + + >>> import hello_ext + >>> print hello_ext.greet() + hello, world + +[c++] + +[:['[*Next stop... Building your Hello World module from start to finish...]]] + +[endsect] +[section:hello Building Hello World] + +[h2 From Start To Finish] + +Now the first thing you'd want to do is to build the Hello World module and +try it for yourself in Python. In this section, we will outline the steps +necessary to achieve that. We will use the build tool that comes bundled +with every boost distribution: [*bjam]. + +[note [*Building without bjam] + +Besides bjam, there are of course other ways to get your module built. +What's written here should not be taken as "the one and only way". +There are of course other build tools apart from [^bjam]. + +Take note however that the preferred build tool for Boost.Python is bjam. +There are so many ways to set up the build incorrectly. Experience shows +that 90% of the "I can't build Boost.Python" problems come from people +who had to use a different tool. +] + +We will skip over the details. Our objective will be to simply create +the hello world module and run it in Python. For a complete reference to +building Boost.Python, check out: [@../../../building.html +building.html]. After this brief ['bjam] tutorial, we should have built +the DLLs and run a python program using the extension. + +The tutorial example can be found in the directory: +[^libs/python/example/tutorial]. There, you can find: + +* hello.cpp +* hello.py +* Jamroot + +The [^hello.cpp] file is our C++ hello world example. The [^Jamroot] is +a minimalist ['bjam] script that builds the DLLs for us. Finally, +[^hello.py] is our Python program that uses the extension in +[^hello.cpp]. + +Before anything else, you should have the bjam executable in your boost +directory or somewhere in your path such that [^bjam] can be executed in +the command line. Pre-built Boost.Jam executables are available for most +platforms. The complete list of Bjam executables can be found +[@http://sourceforge.net/project/showfiles.php?group_id=7586 here]. + +[h2 Let's Jam!] +__jam__ + +[@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot +file. Simply copy the file and tweak [^use-project boost] to where your +boost root directory is and your OK. + +The comments contained in the Jamrules file above should be sufficient +to get you going. + +[h2 Running bjam] + +['bjam] is run using your operating system's command line interpreter. + +[:Start it up.] + +A file called user-config.jam in your home directory is used to +configure your tools. In Windows, your home directory can be found by +typing: + +[pre +ECHO %HOMEDRIVE%%HOMEPATH% +] + +into a command prompt window. Your file should at least have the rules +for your compiler and your python installation. A specific example of +this on Windows would be: + +[pre +# MSVC configuration +using msvc : 8.0 ; + +# Python configuration +using python : 2.4 : C:/dev/tools/Python/ ; +] + +The first rule tells Bjam to use the MSVC 8.0 compiler and associated +tools. The second rule provides information on Python, its version and +where it is located. The above assumes that the Python installation is +in [^C:/dev/tools\/Python/]. If you have one fairly "standard" python +installation for your platform, you might not need to do this. + +Now we are ready... Be sure to [^cd] to [^libs/python/example/tutorial] +where the tutorial [^"hello.cpp"] and the [^"Jamroot"] is situated. + +Finally: + + bjam + +It should be building now: + +[pre +cd C:\dev\boost\libs\python\example\tutorial +bjam +...patience... +...found 1101 targets... +...updating 35 targets... +] + +And so on... Finally: + +[pre + Creating library /path-to-boost_python.dll/ + Creating library /path-to-'''hello_ext'''.exp/ +'''**passed**''' ... hello.test +...updated 35 targets... +] + +Or something similar. If all is well, you should now have built the DLLs and +run the Python program. + +[:[*There you go... Have fun!]] + +[endsect] +[section:exposing Exposing Classes] + +Now let's expose a C++ class to Python. + +Consider a C++ class/struct that we want to expose to Python: + + struct World + { + void set(std::string msg) { this->msg = msg; } + std::string greet() { return msg; } + std::string msg; + }; + +We can expose this to Python by writing a corresponding Boost.Python +C++ Wrapper: + + #include + using namespace boost::python; + + BOOST_PYTHON_MODULE(hello) + { + class_("World") + .def("greet", &World::greet) + .def("set", &World::set) + ; + } + +Here, we wrote a C++ class wrapper that exposes the member functions +[^greet] and [^set]. Now, after building our module as a shared library, we +may use our class [^World] in Python. Here's a sample Python session: + +[python] + + >>> import hello + >>> planet = hello.World() + >>> planet.set('howdy') + >>> planet.greet() + 'howdy' + +[section Constructors] + +Our previous example didn't have any explicit constructors. +Since [^World] is declared as a plain struct, it has an implicit default +constructor. Boost.Python exposes the default constructor by default, +which is why we were able to write + + >>> planet = hello.World() + +We may wish to wrap a class with a non-default constructor. Let us +build on our previous example: + +[c++] + + struct World + { + World(std::string msg): msg(msg) {} // added constructor + void set(std::string msg) { this->msg = msg; } + std::string greet() { return msg; } + std::string msg; + }; + +This time [^World] has no default constructor; our previous +wrapping code would fail to compile when the library tried to expose +it. We have to tell [^class_] about the constructor we want to +expose instead. + + #include + using namespace boost::python; + + BOOST_PYTHON_MODULE(hello) + { + class_("World", init()) + .def("greet", &World::greet) + .def("set", &World::set) + ; + } + +[^init()] exposes the constructor taking in a +[^std::string] (in Python, constructors are spelled +"[^"__init__"]"). + +We can expose additional constructors by passing more [^init<...>]s to +the [^def()] member function. Say for example we have another World +constructor taking in two doubles: + + class_("World", init()) + .def(init()) + .def("greet", &World::greet) + .def("set", &World::set) + ; + +On the other hand, if we do not wish to expose any constructors at +all, we may use [^no_init] instead: + + class_("Abstract", no_init) + +This actually adds an [^__init__] method which always raises a +Python RuntimeError exception. + +[endsect] +[section Class Data Members] + +Data members may also be exposed to Python so that they can be +accessed as attributes of the corresponding Python class. Each data +member that we wish to be exposed may be regarded as [*read-only] or +[*read-write]. Consider this class [^Var]: + + struct Var + { + Var(std::string name) : name(name), value() {} + std::string const name; + float value; + }; + +Our C++ [^Var] class and its data members can be exposed to Python: + + class_("Var", init()) + .def_readonly("name", &Var::name) + .def_readwrite("value", &Var::value); + +Then, in Python, assuming we have placed our Var class inside the namespace +hello as we did before: + +[python] + + >>> x = hello.Var('pi') + >>> x.value = 3.14 + >>> print x.name, 'is around', x.value + pi is around 3.14 + +Note that [^name] is exposed as [*read-only] while [^value] is exposed +as [*read-write]. + + >>> x.name = 'e' # can't change name + Traceback (most recent call last): + File "", line 1, in ? + AttributeError: can't set attribute + +[endsect] +[section Class Properties] + +In C++, classes with public data members are usually frowned +upon. Well designed classes that take advantage of encapsulation hide +the class' data members. The only way to access the class' data is +through access (getter/setter) functions. Access functions expose class +properties. Here's an example: + +[c++] + + struct Num + { + Num(); + float get() const; + void set(float value); + ... + }; + +However, in Python attribute access is fine; it doesn't neccessarily break +encapsulation to let users handle attributes directly, because the +attributes can just be a different syntax for a method call. Wrapping our +[^Num] class using Boost.Python: + + class_("Num") + .add_property("rovalue", &Num::get) + .add_property("value", &Num::get, &Num::set); + +And at last, in Python: + +[python] + + >>> x = Num() + >>> x.value = 3.14 + >>> x.value, x.rovalue + (3.14, 3.14) + >>> x.rovalue = 2.17 # error! + +Take note that the class property [^rovalue] is exposed as [*read-only] +since the [^rovalue] setter member function is not passed in: + +[c++] + + .add_property("rovalue", &Num::get) + +[endsect] +[section Inheritance] + +In the previous examples, we dealt with classes that are not polymorphic. +This is not often the case. Much of the time, we will be wrapping +polymorphic classes and class hierarchies related by inheritance. We will +often have to write Boost.Python wrappers for classes that are derived from +abstract base classes. + +Consider this trivial inheritance structure: + + struct Base { virtual ~Base(); }; + struct Derived : Base {}; + +And a set of C++ functions operating on [^Base] and [^Derived] object +instances: + + void b(Base*); + void d(Derived*); + Base* factory() { return new Derived; } + +We've seen how we can wrap the base class [^Base]: + + class_("Base") + /*...*/ + ; + +Now we can inform Boost.Python of the inheritance relationship between +[^Derived] and its base class [^Base]. Thus: + + class_ >("Derived") + /*...*/ + ; + +Doing so, we get some things for free: + +# Derived automatically inherits all of Base's Python methods + (wrapped C++ member functions) +# [*If] Base is polymorphic, [^Derived] objects which have been passed to + Python via a pointer or reference to [^Base] can be passed where a pointer + or reference to [^Derived] is expected. + +Now, we will expose the C++ free functions [^b] and [^d] and [^factory]: + + def("b", b); + def("d", d); + def("factory", factory); + +Note that free function [^factory] is being used to generate new +instances of class [^Derived]. In such cases, we use +[^return_value_policy] to instruct Python to adopt +the pointer to [^Base] and hold the instance in a new Python [^Base] +object until the the Python object is destroyed. We will see more of +Boost.Python [link python.call_policies call policies] later. + + // Tell Python to take ownership of factory's result + def("factory", factory, + return_value_policy()); + +[endsect] + +[section Class Virtual Functions] + +In this section, we will learn how to make functions behave polymorphically +through virtual functions. Continuing our example, let us add a virtual function +to our [^Base] class: + + struct Base + { + virtual ~Base() {} + virtual int f() = 0; + }; + +One of the goals of Boost.Python is to be minimally intrusive on an existing C++ +design. In principle, it should be possible to expose the interface for a 3rd +party library without changing it. It is not ideal to add anything to our class +`Base`. Yet, when you have a virtual function that's going to be overridden in +Python and called polymorphically *from C++*, we'll need to add some +scaffoldings to make things work properly. What we'll do is write a class +wrapper that derives from `Base` that will unintrusively hook into the virtual +functions so that a Python override may be called: + + struct BaseWrap : Base, wrapper + { + int f() + { + return this->get_override("f")(); + } + }; + +Notice too that in addition to inheriting from `Base`, we also multiply- +inherited `wrapper` (See [@../../../v2/wrapper.html Wrapper]). The +`wrapper` template makes the job of wrapping classes that are meant to +overridden in Python, easier. + +[blurb __alert__ [*MSVC6/7 Workaround] + +If you are using Microsoft Visual C++ 6 or 7, you have to write `f` as: + +`return call(this->get_override("f").ptr());`.] + +BaseWrap's overridden virtual member function `f` in effect calls the +corresponding method of the Python object through `get_override`. + +Finally, exposing `Base`: + + class_("Base") + .def("f", pure_virtual(&Base::f)) + ; + +`pure_virtual` signals Boost.Python that the function `f` is a pure virtual +function. + +[note [*member function and methods] + +Python, like many object oriented languages uses the term [*methods]. +Methods correspond roughly to C++'s [*member functions]] + +[endsect] + +[section Virtual Functions with Default Implementations] + +We've seen in the previous section how classes with pure virtual functions are +wrapped using Boost.Python's [@../../../v2/wrapper.html class wrapper] +facilities. If we wish to wrap [*non]-pure-virtual functions instead, the +mechanism is a bit different. + +Recall that in the [link python.class_virtual_functions previous section], we +wrapped a class with a pure virtual function that we then implemented in C++, or +Python classes derived from it. Our base class: + + struct Base + { + virtual int f() = 0; + }; + +had a pure virtual function [^f]. If, however, its member function [^f] was +not declared as pure virtual: + + struct Base + { + virtual ~Base() {} + virtual int f() { return 0; } + }; + +We wrap it this way: + + struct BaseWrap : Base, wrapper + { + int f() + { + if (override f = this->get_override("f")) + return f(); // *note* + return Base::f(); + } + + int default_f() { return this->Base::f(); } + }; + +Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an +override for `f`. If none, then we call `Base::f()`. + +[blurb __alert__ [*MSVC6/7 Workaround] + +If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line +with the `*note*` as: + +`return call(f.ptr());`.] + +Finally, exposing: + + class_("Base") + .def("f", &Base::f, &BaseWrap::default_f) + ; + +Take note that we expose both `&Base::f` and `&BaseWrap::default_f`. +Boost.Python needs to keep track of 1) the dispatch function [^f] and 2) the +forwarding function to its default implementation [^default_f]. There's a +special [^def] function for this purpose. + +In Python, the results would be as expected: + +[python] + + >>> base = Base() + >>> class Derived(Base): + ... def f(self): + ... return 42 + ... + >>> derived = Derived() + +Calling [^base.f()]: + + >>> base.f() + 0 + +Calling [^derived.f()]: + + >>> derived.f() + 42 + +[endsect] +[section Class Operators/Special Functions] + +[h2 Python Operators] + +C is well known for the abundance of operators. C++ extends this to the +extremes by allowing operator overloading. Boost.Python takes advantage of +this and makes it easy to wrap C++ operator-powered classes. + +Consider a file position class [^FilePos] and a set of operators that take +on FilePos instances: + +[c++] + + class FilePos { /*...*/ }; + + FilePos operator+(FilePos, int); + FilePos operator+(int, FilePos); + int operator-(FilePos, FilePos); + FilePos operator-(FilePos, int); + FilePos& operator+=(FilePos&, int); + FilePos& operator-=(FilePos&, int); + bool operator<(FilePos, FilePos); + +The class and the various operators can be mapped to Python rather easily +and intuitively: + + class_("FilePos") + .def(self + int()) // __add__ + .def(int() + self) // __radd__ + .def(self - self) // __sub__ + .def(self - int()) // __sub__ + .def(self += int()) // __iadd__ + .def(self -= other()) + .def(self < self); // __lt__ + +The code snippet above is very clear and needs almost no explanation at +all. It is virtually the same as the operators' signatures. Just take +note that [^self] refers to FilePos object. Also, not every class [^T] that +you might need to interact with in an operator expression is (cheaply) +default-constructible. You can use [^other()] in place of an actual +[^T] instance when writing "self expressions". + +[h2 Special Methods] + +Python has a few more ['Special Methods]. Boost.Python supports all of the +standard special method names supported by real Python class instances. A +similar set of intuitive interfaces can also be used to wrap C++ functions +that correspond to these Python ['special functions]. Example: + + class Rational + { public: operator double() const; }; + + Rational pow(Rational, Rational); + Rational abs(Rational); + ostream& operator<<(ostream&,Rational); + + class_("Rational") + .def(float_(self)) // __float__ + .def(pow(self, other)) // __pow__ + .def(abs(self)) // __abs__ + .def(str(self)) // __str__ + ; + +Need we say more? + +[note What is the business of `operator<<`? +Well, the method `str` requires the `operator<<` to do its work (i.e. +`operator<<` is used by the method defined by `def(str(self))`.] + +[endsect] +[endsect] [/ Exposing Classes ] + +[section Functions] + +In this chapter, we'll look at Boost.Python powered functions in closer +detail. We will see some facilities to make exposing C++ functions to +Python safe from potential pifalls such as dangling pointers and +references. We will also see facilities that will make it even easier for +us to expose C++ functions that take advantage of C++ features such as +overloading and default arguments. + +[:['Read on...]] + +But before you do, you might want to fire up Python 2.2 or later and type +[^>>> import this]. + +[pre +>>> import this +The Zen of Python, by Tim Peters +Beautiful is better than ugly. +Explicit is better than implicit. +Simple is better than complex. +Complex is better than complicated. +Flat is better than nested. +Sparse is better than dense. +Readability counts. +Special cases aren't special enough to break the rules. +Although practicality beats purity. +Errors should never pass silently. +Unless explicitly silenced. +In the face of ambiguity, refuse the temptation to guess. +There should be one-- and preferably only one --obvious way to do it +Although that way may not be obvious at first unless you're Dutch. +Now is better than never. +Although never is often better than *right* now. +If the implementation is hard to explain, it's a bad idea. +If the implementation is easy to explain, it may be a good idea. +Namespaces are one honking great idea -- let's do more of those! +] + +[section Call Policies] + +In C++, we often deal with arguments and return types such as pointers +and references. Such primitive types are rather, ummmm, low level and +they really don't tell us much. At the very least, we don't know the +owner of the pointer or the referenced object. No wonder languages +such as Java and Python never deal with such low level entities. In +C++, it's usually considered a good practice to use smart pointers +which exactly describe ownership semantics. Still, even good C++ +interfaces use raw references and pointers sometimes, so Boost.Python +must deal with them. To do this, it may need your help. Consider the +following C++ function: + + X& f(Y& y, Z* z); + +How should the library wrap this function? A naive approach builds a +Python X object around result reference. This strategy might or might +not work out. Here's an example where it didn't + + >>> x = f(y, z) # x refers to some C++ X + >>> del y + >>> x.some_method() # CRASH! + +What's the problem? + +Well, what if f() was implemented as shown below: + + X& f(Y& y, Z* z) + { + y.z = z; + return y.x; + } + +The problem is that the lifetime of result X& is tied to the lifetime +of y, because the f() returns a reference to a member of the y +object. This idiom is is not uncommon and perfectly acceptable in the +context of C++. However, Python users should not be able to crash the +system just by using our C++ interface. In this case deleting y will +invalidate the reference to X. We have a dangling reference. + +Here's what's happening: + +# [^f] is called passing in a reference to [^y] and a pointer to [^z] +# A reference to [^y.x] is returned +# [^y] is deleted. [^x] is a dangling reference +# [^x.some_method()] is called +# [*BOOM!] + +We could copy result into a new object: + +[python] + + >>> f(y, z).set(42) # Result disappears + >>> y.x.get() # No crash, but still bad + 3.14 + +This is not really our intent of our C++ interface. We've broken our +promise that the Python interface should reflect the C++ interface as +closely as possible. + +Our problems do not end there. Suppose Y is implemented as follows: + +[c++] + + struct Y + { + X x; Z* z; + int z_value() { return z->value(); } + }; + +Notice that the data member [^z] is held by class Y using a raw +pointer. Now we have a potential dangling pointer problem inside Y: + + >>> x = f(y, z) # y refers to z + >>> del z # Kill the z object + >>> y.z_value() # CRASH! + +For reference, here's the implementation of [^f] again: + + X& f(Y& y, Z* z) + { + y.z = z; + return y.x; + } + +Here's what's happening: + +# [^f] is called passing in a reference to [^y] and a pointer to [^z] +# A pointer to [^z] is held by [^y] +# A reference to [^y.x] is returned +# [^z] is deleted. [^y.z] is a dangling pointer +# [^y.z_value()] is called +# [^z->value()] is called +# [*BOOM!] + +[h2 Call Policies] + +Call Policies may be used in situations such as the example detailed above. +In our example, [^return_internal_reference] and [^with_custodian_and_ward] +are our friends: + + def("f", f, + return_internal_reference<1, + with_custodian_and_ward<1, 2> >()); + +What are the [^1] and [^2] parameters, you ask? + + return_internal_reference<1 + +Informs Boost.Python that the first argument, in our case [^Y& y], is the +owner of the returned reference: [^X&]. The "[^1]" simply specifies the +first argument. In short: "return an internal reference [^X&] owned by the +1st argument [^Y& y]". + + with_custodian_and_ward<1, 2> + +Informs Boost.Python that the lifetime of the argument indicated by ward +(i.e. the 2nd argument: [^Z* z]) is dependent on the lifetime of the +argument indicated by custodian (i.e. the 1st argument: [^Y& y]). + +It is also important to note that we have defined two policies above. Two +or more policies can be composed by chaining. Here's the general syntax: + + policy1 > > + +Here is the list of predefined call policies. A complete reference detailing +these can be found [@../../../v2/reference.html#models_of_call_policies here]. + +* [*with_custodian_and_ward]: Ties lifetimes of the arguments +* [*with_custodian_and_ward_postcall]: Ties lifetimes of the arguments and results +* [*return_internal_reference]: Ties lifetime of one argument to that of result +* [*return_value_policy with T one of:] + * [*reference_existing_object]: naive (dangerous) approach + * [*copy_const_reference]: Boost.Python v1 approach + * [*copy_non_const_reference]: + * [*manage_new_object]: Adopt a pointer and hold the instance + +[blurb :-) [*Remember the Zen, Luke:] + +"Explicit is better than implicit" + +"In the face of ambiguity, refuse the temptation to guess" +] + +[endsect] +[section Overloading] + +The following illustrates a scheme for manually wrapping an overloaded +member functions. Of course, the same technique can be applied to wrapping +overloaded non-member functions. + +We have here our C++ class: + + struct X + { + bool f(int a) + { + return true; + } + + bool f(int a, double b) + { + return true; + } + + bool f(int a, double b, char c) + { + return true; + } + + int f(int a, int b, int c) + { + return a + b + c; + }; + }; + +Class X has 4 overloaded functions. We will start by introducing some +member function pointer variables: + + bool (X::*fx1)(int) = &X::f; + bool (X::*fx2)(int, double) = &X::f; + bool (X::*fx3)(int, double, char)= &X::f; + int (X::*fx4)(int, int, int) = &X::f; + +With these in hand, we can proceed to define and wrap this for Python: + + .def("f", fx1) + .def("f", fx2) + .def("f", fx3) + .def("f", fx4) + +[endsect] +[section Default Arguments] + +Boost.Python wraps (member) function pointers. Unfortunately, C++ function +pointers carry no default argument info. Take a function [^f] with default +arguments: + + int f(int, double = 3.14, char const* = "hello"); + +But the type of a pointer to the function [^f] has no information +about its default arguments: + + int(*g)(int,double,char const*) = f; // defaults lost! + +When we pass this function pointer to the [^def] function, there is no way +to retrieve the default arguments: + + def("f", f); // defaults lost! + +Because of this, when wrapping C++ code, we had to resort to manual +wrapping as outlined in the [link python.overloading previous section], or +writing thin wrappers: + + // write "thin wrappers" + int f1(int x) { f(x); } + int f2(int x, double y) { f(x,y); } + + /*...*/ + + // in module init + def("f", f); // all arguments + def("f", f2); // two arguments + def("f", f1); // one argument + +When you want to wrap functions (or member functions) that either: + +* have default arguments, or +* are overloaded with a common sequence of initial arguments + +[h2 BOOST_PYTHON_FUNCTION_OVERLOADS] + +Boost.Python now has a way to make it easier. For instance, given a function: + + int foo(int a, char b = 1, unsigned c = 2, double d = 3) + { + /*...*/ + } + +The macro invocation: + + BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4) + +will automatically create the thin wrappers for us. This macro will create +a class [^foo_overloads] that can be passed on to [^def(...)]. The third +and fourth macro argument are the minimum arguments and maximum arguments, +respectively. In our [^foo] function the minimum number of arguments is 1 +and the maximum number of arguments is 4. The [^def(...)] function will +automatically add all the foo variants for us: + + def("foo", foo, foo_overloads()); + +[h2 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] + +Objects here, objects there, objects here there everywhere. More frequently +than anything else, we need to expose member functions of our classes to +Python. Then again, we have the same inconveniences as before when default +arguments or overloads with a common sequence of initial arguments come +into play. Another macro is provided to make this a breeze. + +Like [^BOOST_PYTHON_FUNCTION_OVERLOADS], +[^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] may be used to automatically create +the thin wrappers for wrapping member functions. Let's have an example: + + struct george + { + void + wack_em(int a, int b = 0, char c = 'x') + { + /*...*/ + } + }; + +The macro invocation: + + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3) + +will generate a set of thin wrappers for george's [^wack_em] member function +accepting a minimum of 1 and a maximum of 3 arguments (i.e. the third and +fourth macro argument). The thin wrappers are all enclosed in a class named +[^george_overloads] that can then be used as an argument to [^def(...)]: + + .def("wack_em", &george::wack_em, george_overloads()); + +See the [@../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference] +for details. + +[h2 init and optional] + +A similar facility is provided for class constructors, again, with +default arguments or a sequence of overloads. Remember [^init<...>]? For example, +given a class X with a constructor: + + struct X + { + X(int a, char b = 'D', std::string c = "constructor", double d = 0.0); + /*...*/ + } + +You can easily add this constructor to Boost.Python in one shot: + + .def(init >()) + +Notice the use of [^init<...>] and [^optional<...>] to signify the default +(optional arguments). + +[endsect] +[section Auto-Overloading] + +It was mentioned in passing in the previous section that +[^BOOST_PYTHON_FUNCTION_OVERLOADS] and [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] +can also be used for overloaded functions and member functions with a +common sequence of initial arguments. Here is an example: + + void foo() + { + /*...*/ + } + + void foo(bool a) + { + /*...*/ + } + + void foo(bool a, int b) + { + /*...*/ + } + + void foo(bool a, int b, char c) + { + /*...*/ + } + +Like in the previous section, we can generate thin wrappers for these +overloaded functions in one-shot: + + BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3) + +Then... + + .def("foo", (void(*)(bool, int, char))0, foo_overloads()); + +Notice though that we have a situation now where we have a minimum of zero +(0) arguments and a maximum of 3 arguments. + +[h2 Manual Wrapping] + +It is important to emphasize however that [*the overloaded functions must +have a common sequence of initial arguments]. Otherwise, our scheme above +will not work. If this is not the case, we have to wrap our functions +[link python.overloading manually]. + +Actually, we can mix and match manual wrapping of overloaded functions and +automatic wrapping through [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] and +its sister, [^BOOST_PYTHON_FUNCTION_OVERLOADS]. Following up on our example +presented in the section [link python.overloading on overloading], since the +first 4 overload functins have a common sequence of initial arguments, we +can use [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] to automatically wrap the +first three of the [^def]s and manually wrap just the last. Here's +how we'll do this: + + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4) + +Create a member function pointers as above for both X::f overloads: + + bool (X::*fx1)(int, double, char) = &X::f; + int (X::*fx2)(int, int, int) = &X::f; + +Then... + + .def("f", fx1, xf_overloads()); + .def("f", fx2) + +[endsect] +[endsect] [/ Functions ] + +[section:object Object Interface] + +Python is dynamically typed, unlike C++ which is statically typed. Python +variables may hold an integer, a float, list, dict, tuple, str, long etc., +among other things. In the viewpoint of Boost.Python and C++, these +Pythonic variables are just instances of class [^object]. We will see in +this chapter how to deal with Python objects. + +As mentioned, one of the goals of Boost.Python is to provide a +bidirectional mapping between C++ and Python while maintaining the Python +feel. Boost.Python C++ [^object]s are as close as possible to Python. This +should minimize the learning curve significantly. + +[$images/python.png] + +[section Basic Interface] + +Class [^object] wraps [^PyObject*]. All the intricacies of dealing with +[^PyObject]s such as managing reference counting are handled by the +[^object] class. C++ object interoperability is seamless. Boost.Python C++ +[^object]s can in fact be explicitly constructed from any C++ object. + +To illustrate, this Python code snippet: + +[python] + + def f(x, y): + if (y == 'foo'): + x[3:7] = 'bar' + else: + x.items += y(3, x) + return x + + def getfunc(): + return f; + +Can be rewritten in C++ using Boost.Python facilities this way: + +[c++] + + object f(object x, object y) { + if (y == "foo") + x.slice(3,7) = "bar"; + else + x.attr("items") += y(3, x); + return x; + } + object getfunc() { + return object(f); + } + +Apart from cosmetic differences due to the fact that we are writing the +code in C++, the look and feel should be immediately apparent to the Python +coder. + +[endsect] +[section Derived Object types] + +Boost.Python comes with a set of derived [^object] types corresponding to +that of Python's: + +* list +* dict +* tuple +* str +* long_ +* enum + +These derived [^object] types act like real Python types. For instance: + + str(1) ==> "1" + +Wherever appropriate, a particular derived [^object] has corresponding +Python type's methods. For instance, [^dict] has a [^keys()] method: + + d.keys() + +[^make_tuple] is provided for declaring ['tuple literals]. Example: + + make_tuple(123, 'D', "Hello, World", 0.0); + +In C++, when Boost.Python [^object]s are used as arguments to functions, +subtype matching is required. For example, when a function [^f], as +declared below, is wrapped, it will only accept instances of Python's +[^str] type and subtypes. + + void f(str name) + { + object n2 = name.attr("upper")(); // NAME = name.upper() + str NAME = name.upper(); // better + object msg = "%s is bigger than %s" % make_tuple(NAME,name); + } + +In finer detail: + + str NAME = name.upper(); + +Illustrates that we provide versions of the str type's methods as C++ +member functions. + + object msg = "%s is bigger than %s" % make_tuple(NAME,name); + +Demonstrates that you can write the C++ equivalent of [^"format" % x,y,z] +in Python, which is useful since there's no easy way to do that in std C++. + +[blurb + __alert__ [*Beware] the common pitfall of forgetting that the constructors + of most of Python's mutable types make copies, just as in Python. +] + +Python: +[python] + + >>> d = dict(x.__dict__) # copies x.__dict__ + >>> d['whatever'] = 3 # modifies the copy + +C++: +[c++] + + dict d(x.attr("__dict__")); // copies x.__dict__ + d['whatever'] = 3; // modifies the copy + +[h2 class_ as objects] + +Due to the dynamic nature of Boost.Python objects, any [^class_] may +also be one of these types! The following code snippet wraps the class +(type) object. + +We can use this to create wrapped instances. Example: + + object vec345 = ( + class_("Vec2", init()) + .def_readonly("length", &Point::length) + .def_readonly("angle", &Point::angle) + )(3.0, 4.0); + + assert(vec345.attr("length") == 5.0); + +[endsect] +[section Extracting C++ objects] + +At some point, we will need to get C++ values out of object instances. This +can be achieved with the [^extract] function. Consider the following: + + double x = o.attr("length"); // compile error + +In the code above, we got a compiler error because Boost.Python +[^object] can't be implicitly converted to [^double]s. Instead, what +we wanted to do above can be achieved by writing: + + double l = extract(o.attr("length")); + Vec2& v = extract(o); + assert(l == v.length()); + +The first line attempts to extract the "length" attribute of the Boost.Python +[^object]. The second line attempts to ['extract] the [^Vec2] object from held +by the Boost.Python [^object]. + +Take note that we said "attempt to" above. What if the Boost.Python [^object] +does not really hold a [^Vec2] type? This is certainly a possibility considering +the dynamic nature of Python [^object]s. To be on the safe side, if the C++ type +can't be extracted, an appropriate exception is thrown. To avoid an exception, +we need to test for extractibility: + + extract x(o); + if (x.check()) { + Vec2& v = x(); ... + +__tip__ The astute reader might have noticed that the [^extract] +facility in fact solves the mutable copying problem: + + dict d = extract(x.attr("__dict__")); + d["whatever"] = 3; // modifies x.__dict__ ! + + +[endsect] +[section Enums] + +Boost.Python has a nifty facility to capture and wrap C++ enums. While +Python has no [^enum] type, we'll often want to expose our C++ enums to +Python as an [^int]. Boost.Python's enum facility makes this easy while +taking care of the proper conversions from Python's dynamic typing to C++'s +strong static typing (in C++, ints cannot be implicitly converted to +enums). To illustrate, given a C++ enum: + + enum choice { red, blue }; + +the construct: + + enum_("choice") + .value("red", red) + .value("blue", blue) + ; + +can be used to expose to Python. The new enum type is created in the +current [^scope()], which is usually the current module. The snippet above +creates a Python class derived from Python's [^int] type which is +associated with the C++ type passed as its first parameter. + +[note [*what is a scope?] + +The scope is a class that has an associated global Python object which +controls the Python namespace in which new extension classes and wrapped +functions will be defined as attributes. Details can be found +[@../../../v2/scope.html here].] + +You can access those values in Python as + +[python] + + >>> my_module.choice.red + my_module.choice.red + +where my_module is the module where the enum is declared. You can also +create a new scope around a class: + +[c++] + + scope in_X = class_("X") + .def( ... ) + .def( ... ) + ; + + // Expose X::nested as X.nested + enum_("nested") + .value("red", red) + .value("blue", blue) + ; + +[def Py_Initialize [@http://www.python.org/doc/current/api/initialization.html#l2h-652 Py_Initialize]] +[def Py_Finalize [@http://www.python.org/doc/current/api/initialization.html#l2h-656 Py_Finalize]] +[def Py_XINCREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-65 Py_XINCREF]] +[def Py_XDECREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-67 Py_XDECREF]] +[def PyImport_AppendInittab [@http://www.python.org/doc/current/api/importing.html#l2h-137 PyImport_AppendInittab]] +[def PyImport_AddModule [@http://www.python.org/doc/current/api/importing.html#l2h-125 PyImport_AddModule]] +[def PyModule_New [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-591 PyModule_New]] +[def PyModule_GetDict [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-594 PyModule_GetDict]] + +[endsect] + +[section:creating_python_object Creating `boost::python::object` from `PyObject*`] + +When you want a `boost::python::object` to manage a pointer to `PyObject*` pyobj one does: + + boost::python::object o(boost::python::handle<>(pyobj)); + +In this case, the `o` object, manages the `pyobj`, it won’t increase the reference count on construction. + +Otherwise, to use a borrowed reference: + + boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj))); + +In this case, `Py_INCREF` is called, so `pyobj` is not destructed when object o goes out of scope. + +[endsect] [/ creating_python_object ] + +[endsect] [/ Object Interface] + +[section Embedding] + +By now you should know how to use Boost.Python to call your C++ code from +Python. However, sometimes you may need to do the reverse: call Python code +from the C++-side. This requires you to ['embed] the Python interpreter +into your C++ program. + +Currently, Boost.Python does not directly support everything you'll need +when embedding. Therefore you'll need to use the +[@http://www.python.org/doc/current/api/api.html Python/C API] to fill in +the gaps. However, Boost.Python already makes embedding a lot easier and, +in a future version, it may become unnecessary to touch the Python/C API at +all. So stay tuned... :-) + +[h2 Building embedded programs] + +To be able to embed python into your programs, you have to link to +both Boost.Python's as well as Python's own runtime library. + +Boost.Python's library comes in two variants. Both are located +in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the +variants are called [^boost_python.lib] (for release builds) and +[^boost_python_debug.lib] (for debugging). If you can't find the libraries, +you probably haven't built Boost.Python yet. See +[@../../../building.html Building and Testing] on how to do this. + +Python's library can be found in the [^/libs] subdirectory of +your Python directory. On Windows it is called pythonXY.lib where X.Y is +your major Python version number. + +Additionally, Python's [^/include] subdirectory has to be added to your +include path. + +In a Jamfile, all the above boils down to: + +[pre +projectroot c:\projects\embedded_program ; # location of the program + +# bring in the rules for python +SEARCH on python.jam = $(BOOST_BUILD_PATH) ; +include python.jam ; + +exe embedded_program # name of the executable + : #sources + embedded_program.cpp + : # requirements + boost_python c:\boost\libs\python + $(PYTHON_PROPERTIES) + $(PYTHON_LIB_PATH) + $(PYTHON_EMBEDDED_LIBRARY) ; +] + +[h2 Getting started] + +Being able to build is nice, but there is nothing to build yet. Embedding +the Python interpreter into one of your C++ programs requires these 4 +steps: + +# '''#include''' [^] + +# Call Py_Initialize() to start the interpreter and create the [^__main__] module. + +# Call other Python C API routines to use the interpreter. + +[/ # Call Py_Finalize() to stop the interpreter and release its resources.] + +[note [*Note that at this time you must not call Py_Finalize() to stop the +interpreter. This may be fixed in a future version of boost.python.] +] + +(Of course, there can be other C++ code between all of these steps.) + +[:['[*Now that we can embed the interpreter in our programs, lets see how to put it to use...]]] + +[section Using the interpreter] + +As you probably already know, objects in Python are reference-counted. +Naturally, the [^PyObject]s of the Python C API are also reference-counted. +There is a difference however. While the reference-counting is fully +automatic in Python, the Python C API requires you to do it +[@http://www.python.org/doc/current/c-api/refcounting.html by hand]. This is +messy and especially hard to get right in the presence of C++ exceptions. +Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and +[@../../../v2/object.html object] class templates to automate the process. + +[h2 Running Python code] + +Boost.python provides three related functions to run Python code from C++. + + object eval(str expression, object globals = object(), object locals = object()) + object exec(str code, object globals = object(), object locals = object()) + object exec_file(str filename, object globals = object(), object locals = object()) + +eval evaluates the given expression and returns the resulting value. +exec executes the given code (typically a set of statements) returning the result, +and exec_file executes the code contained in the given file. + +The [^globals] and [^locals] parameters are Python dictionaries +containing the globals and locals of the context in which to run the code. +For most intents and purposes you can use the namespace dictionary of the +[^__main__] module for both parameters. + +Boost.python provides a function to import a module: + + object import(str name) + +import imports a python module (potentially loading it into the running process +first), and returns it. + +Let's import the [^__main__] module and run some Python code in its namespace: + + object main_module = import("__main__"); + object main_namespace = main_module.attr("__dict__"); + + object ignored = exec("hello = file('hello.txt', 'w')\n" + "hello.write('Hello world!')\n" + "hello.close()", + main_namespace); + +This should create a file called 'hello.txt' in the current directory +containing a phrase that is well-known in programming circles. + +[h2 Manipulating Python objects] + +Often we'd like to have a class to manipulate Python objects. +But we have already seen such a class above, and in the +[@python/object.html previous section]: the aptly named [^object] class +and its derivatives. We've already seen that they can be constructed from +a [^handle]. The following examples should further illustrate this fact: + + object main_module = import("__main__"); + object main_namespace = main_module.attr("__dict__"); + object ignored = exec("result = 5 ** 2", main_namespace); + int five_squared = extract(main_namespace["result"]); + +Here we create a dictionary object for the [^__main__] module's namespace. +Then we assign 5 squared to the result variable and read this variable from +the dictionary. Another way to achieve the same result is to use eval instead, +which returns the result directly: + + object result = eval("5 ** 2"); + int five_squared = extract(result); + +[h2 Exception handling] + +If an exception occurs in the evaluation of the python expression, +[@../../../v2/errors.html#error_already_set-spec error_already_set] is thrown: + + try + { + object result = eval("5/0"); + // execution will never get here: + int five_divided_by_zero = extract(result); + } + catch(error_already_set const &) + { + // handle the exception in some way + } + +The [^error_already_set] exception class doesn't carry any information in itself. +To find out more about the Python exception that occurred, you need to use the +[@http://www.python.org/doc/api/exceptionHandling.html exception handling functions] +of the Python C API in your catch-statement. This can be as simple as calling +[@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to +print the exception's traceback to the console, or comparing the type of the +exception with those of the [@http://www.python.org/doc/api/standardExceptions.html +standard exceptions]: + + catch(error_already_set const &) + { + if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) + { + // handle ZeroDivisionError specially + } + else + { + // print all other errors to stderr + PyErr_Print(); + } + } + +(To retrieve even more information from the exception you can use some of the other +exception handling functions listed [@http://www.python.org/doc/api/exceptionHandling.html here].) + +[endsect] +[endsect] [/ Embedding] + +[section Iterators] + +In C++, and STL in particular, we see iterators everywhere. Python also has +iterators, but these are two very different beasts. + +[*C++ iterators:] + +* C++ has 5 type categories (random-access, bidirectional, forward, input, output) +* There are 2 Operation categories: reposition, access +* A pair of iterators is needed to represent a (first/last) range. + +[*Python Iterators:] + +* 1 category (forward) +* 1 operation category (next()) +* Raises StopIteration exception at end + +The typical Python iteration protocol: [^[*for y in x...]] is as follows: + +[python] + + iter = x.__iter__() # get iterator + try: + while 1: + y = iter.next() # get each item + ... # process y + except StopIteration: pass # iterator exhausted + +Boost.Python provides some mechanisms to make C++ iterators play along +nicely as Python iterators. What we need to do is to produce +appropriate `__iter__` function from C++ iterators that is compatible +with the Python iteration protocol. For example: + +[c++] + + object get_iterator = iterator >(); + object iter = get_iterator(v); + object first = iter.next(); + +Or for use in class_<>: + + .def("__iter__", iterator >()) + +[*range] + +We can create a Python savvy iterator using the range function: + +* range(start, finish) +* range(start, finish) + +Here, start/finish may be one of: + +* member data pointers +* member function pointers +* adaptable function object (use Target parameter) + +[*iterator] + +* iterator() + +Given a container [^T], iterator is a shortcut that simply calls [^range] +with &T::begin, &T::end. + +Let's put this into action... Here's an example from some hypothetical +bogon Particle accelerator code: + +[python] + + f = Field() + for x in f.pions: + smash(x) + for y in f.bogons: + count(y) + +Now, our C++ Wrapper: + +[c++] + + class_("Field") + .property("pions", range(&F::p_begin, &F::p_end)) + .property("bogons", range(&F::b_begin, &F::b_end)); + +[*stl_input_iterator] + +So far, we have seen how to expose C++ iterators and ranges to Python. +Sometimes we wish to go the other way, though: we'd like to pass a +Python sequence to an STL algorithm or use it to initialize an STL +container. We need to make a Python iterator look like an STL iterator. +For that, we use `stl_input_iterator<>`. Consider how we might +implement a function that exposes `std::list::assign()` to +Python: + +[c++] + + template + void list_assign(std::list& l, object o) { + // Turn a Python sequence into an STL input range + stl_input_iterator begin(o), end; + l.assign(begin, end); + } + + // Part of the wrapper for list + class_ >("list_int") + .def("assign", &list_assign) + // ... + ; + +Now in Python, we can assign any integer sequence to `list_int` objects: + +[python] + + x = list_int(); + x.assign([1,2,3,4,5]) + +[endsect] +[section:exception Exception Translation] + +All C++ exceptions must be caught at the boundary with Python code. This +boundary is the point where C++ meets Python. Boost.Python provides a +default exception handler that translates selected standard exceptions, +then gives up: + + raise RuntimeError, 'unidentifiable C++ Exception' + +Users may provide custom translation. Here's an example: + + struct PodBayDoorException; + void translator(PodBayDoorException const& x) { + PyErr_SetString(PyExc_UserWarning, "I'm sorry Dave..."); + } + BOOST_PYTHON_MODULE(kubrick) { + register_exception_translator< + PodBayDoorException>(translator); + ... + +[endsect] +[section:techniques General Techniques] + +Here are presented some useful techniques that you can use while wrapping code with Boost.Python. + +[section Creating Packages] + +A Python package is a collection of modules that provide to the user a certain +functionality. If you're not familiar on how to create packages, a good +introduction to them is provided in the +[@http://www.python.org/doc/current/tut/node8.html Python Tutorial]. + +But we are wrapping C++ code, using Boost.Python. How can we provide a nice +package interface to our users? To better explain some concepts, let's work +with an example. + +We have a C++ library that works with sounds: reading and writing various +formats, applying filters to the sound data, etc. It is named (conveniently) +[^sounds]. Our library already has a neat C++ namespace hierarchy, like so: + + sounds::core + sounds::io + sounds::filters + +We would like to present this same hierarchy to the Python user, allowing him +to write code like this: + + import sounds.filters + sounds.filters.echo(...) # echo is a C++ function + +The first step is to write the wrapping code. We have to export each module +separately with Boost.Python, like this: + + /* file core.cpp */ + BOOST_PYTHON_MODULE(core) + { + /* export everything in the sounds::core namespace */ + ... + } + + /* file io.cpp */ + BOOST_PYTHON_MODULE(io) + { + /* export everything in the sounds::io namespace */ + ... + } + + /* file filters.cpp */ + BOOST_PYTHON_MODULE(filters) + { + /* export everything in the sounds::filters namespace */ + ... + } + +Compiling these files will generate the following Python extensions: +[^core.pyd], [^io.pyd] and [^filters.pyd]. + +[note The extension [^.pyd] is used for python extension modules, which +are just shared libraries. Using the default for your system, like [^.so] for +Unix and [^.dll] for Windows, works just as well.] + +Now, we create this directory structure for our Python package: + +[pre +sounds/ + \_\_init\_\_.py + core.pyd + filters.pyd + io.pyd +] + +The file [^\_\_init\_\_.py] is what tells Python that the directory [^sounds/] is +actually a Python package. It can be a empty file, but can also perform some +magic, that will be shown later. + +Now our package is ready. All the user has to do is put [^sounds] into his +[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH] +and fire up the interpreter: + +[python] + + >>> import sounds.io + >>> import sounds.filters + >>> sound = sounds.io.open('file.mp3') + >>> new_sound = sounds.filters.echo(sound, 1.0) + +Nice heh? + +This is the simplest way to create hierarchies of packages, but it is not very +flexible. What if we want to add a ['pure] Python function to the filters +package, for instance, one that applies 3 filters in a sound object at once? +Sure, you can do this in C++ and export it, but why not do so in Python? You +don't have to recompile the extension modules, plus it will be easier to write +it. + +If we want this flexibility, we will have to complicate our package hierarchy a +little. First, we will have to change the name of the extension modules: + +[c++] + + /* file core.cpp */ + BOOST_PYTHON_MODULE(_core) + { + ... + /* export everything in the sounds::core namespace */ + } + +Note that we added an underscore to the module name. The filename will have to +be changed to [^_core.pyd] as well, and we do the same to the other extension modules. +Now, we change our package hierarchy like so: + +[pre +sounds/ + \_\_init\_\_.py + core/ + \_\_init\_\_.py + _core.pyd + filters/ + \_\_init\_\_.py + _filters.pyd + io/ + \_\_init\_\_.py + _io.pyd +] + +Note that we created a directory for each extension module, and added a +\_\_init\_\_.py to each one. But if we leave it that way, the user will have to +access the functions in the core module with this syntax: + +[python] + + >>> import sounds.core._core + >>> sounds.core._core.foo(...) + +which is not what we want. But here enters the [^\_\_init\_\_.py] magic: everything +that is brought to the [^\_\_init\_\_.py] namespace can be accessed directly by the +user. So, all we have to do is bring the entire namespace from [^_core.pyd] +to [^core/\_\_init\_\_.py]. So add this line of code to [^sounds/core/\_\_init\_\_.py]: + + from _core import * + +We do the same for the other packages. Now the user accesses the functions and +classes in the extension modules like before: + + >>> import sounds.filters + >>> sounds.filters.echo(...) + +with the additional benefit that we can easily add pure Python functions to +any module, in a way that the user can't tell the difference between a C++ +function and a Python function. Let's add a ['pure] Python function, +[^echo_noise], to the [^filters] package. This function applies both the +[^echo] and [^noise] filters in sequence in the given [^sound] object. We +create a file named [^sounds/filters/echo_noise.py] and code our function: + + import _filters + def echo_noise(sound): + s = _filters.echo(sound) + s = _filters.noise(sound) + return s + +Next, we add this line to [^sounds/filters/\_\_init\_\_.py]: + + from echo_noise import echo_noise + +And that's it. The user now accesses this function like any other function +from the [^filters] package: + + >>> import sounds.filters + >>> sounds.filters.echo_noise(...) + +[endsect] +[section Extending Wrapped Objects in Python] + +Thanks to Python's flexibility, you can easily add new methods to a class, +even after it was already created: + + >>> class C(object): pass + >>> + >>> # a regular function + >>> def C_str(self): return 'A C instance!' + >>> + >>> # now we turn it in a member function + >>> C.__str__ = C_str + >>> + >>> c = C() + >>> print c + A C instance! + >>> C_str(c) + A C instance! + +Yes, Python rox. :-) + +We can do the same with classes that were wrapped with Boost.Python. Suppose +we have a class [^point] in C++: + +[c++] + + class point {...}; + + BOOST_PYTHON_MODULE(_geom) + { + class_("point")...; + } + +If we are using the technique from the previous session, +[link python.creating_packages Creating Packages], we can code directly +into [^geom/\_\_init\_\_.py]: + +[python] + + from _geom import * + + # a regular function + def point_str(self): + return str((self.x, self.y)) + + # now we turn it into a member function + point.__str__ = point_str + +[*All] point instances created from C++ will also have this member function! +This technique has several advantages: + +* Cut down compile times to zero for these additional functions +* Reduce the memory footprint to virtually zero +* Minimize the need to recompile +* Rapid prototyping (you can move the code to C++ if required without changing the interface) + +You can even add a little syntactic sugar with the use of metaclasses. Let's +create a special metaclass that "injects" methods in other classes. + + # The one Boost.Python uses for all wrapped classes. + # You can use here any class exported by Boost instead of "point" + BoostPythonMetaclass = point.__class__ + + class injector(object): + class __metaclass__(BoostPythonMetaclass): + def __init__(self, name, bases, dict): + for b in bases: + if type(b) not in (self, type): + for k,v in dict.items(): + setattr(b,k,v) + return type.__init__(self, name, bases, dict) + + # inject some methods in the point foo + class more_point(injector, point): + def __repr__(self): + return 'Point(x=%s, y=%s)' % (self.x, self.y) + def foo(self): + print 'foo!' + +Now let's see how it got: + + >>> print point() + Point(x=10, y=10) + >>> point().foo() + foo! + +Another useful idea is to replace constructors with factory functions: + + _point = point + + def point(x=0, y=0): + return _point(x, y) + +In this simple case there is not much gained, but for constructurs with +many overloads and/or arguments this is often a great simplification, again +with virtually zero memory footprint and zero compile-time overhead for +the keyword support. + +[endsect] +[section Reducing Compiling Time] + +If you have ever exported a lot of classes, you know that it takes quite a good +time to compile the Boost.Python wrappers. Plus the memory consumption can +easily become too high. If this is causing you problems, you can split the +class_ definitions in multiple files: + +[c++] + + /* file point.cpp */ + #include + #include + + void export_point() + { + class_("point")...; + } + + /* file triangle.cpp */ + #include + #include + + void export_triangle() + { + class_("triangle")...; + } + +Now you create a file [^main.cpp], which contains the [^BOOST_PYTHON_MODULE] +macro, and call the various export functions inside it. + + void export_point(); + void export_triangle(); + + BOOST_PYTHON_MODULE(_geom) + { + export_point(); + export_triangle(); + } + +Compiling and linking together all this files produces the same result as the +usual approach: + + #include + #include + #include + + BOOST_PYTHON_MODULE(_geom) + { + class_("point")...; + class_("triangle")...; + } + +but the memory is kept under control. + +This method is recommended too if you are developing the C++ library and +exporting it to Python at the same time: changes in a class will only demand +the compilation of a single cpp, instead of the entire wrapper code. + +[note If you're exporting your classes with [@../../../../pyste/index.html Pyste], +take a look at the [^--multiple] option, that generates the wrappers in +various files as demonstrated here.] + +[note This method is useful too if you are getting the error message +['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling +a large source file, as explained in the [@../../../v2/faq.html#c1204 FAQ].] + +[endsect] +[endsect] [/ General Techniques] + + diff --git a/libs/python/doc/tutorial/index.html b/libs/python/doc/tutorial/index.html new file mode 100644 index 0000000000..7924277724 --- /dev/null +++ b/libs/python/doc/tutorial/index.html @@ -0,0 +1,18 @@ + + + + + + + + + + Automatic redirection failed, click this + link  
+

Copyright Beman Dawes, 2001

+

Distributed under the Boost Software License, Version 1.0. (See + accompanying file + LICENSE_1_0.txt or copy at + www.boost.org/LICENSE_1_0.txt)

+ + diff --git a/libs/python/doc/v2/Apr2002.html b/libs/python/doc/v2/Apr2002.html new file mode 100644 index 0000000000..62350defa4 --- /dev/null +++ b/libs/python/doc/v2/Apr2002.html @@ -0,0 +1,166 @@ + + + + + + + +Boost.Python - April 2002 Progress Report + + + + + + + +
+

+

+
+

Boost.Python

+

April 2002 Progress Report

+
+
+

Contents

+
+
Accomplishments
+
+
Arbitrary Arity Support
+
New Callback Interface
+
Call Policies for Construtors
+
Real Users, Real Bugs
+
New Insights
+
Boost.Python V1 Maintenance
+
+ +
What's Missing
+ +
+ +

Accomplishments

+ +April was a short month as far as Boost.Python was concerned, since +the spring ISO C++ Committee Meeting (and associated vacation) +occupied me for the 2nd half of the month. However, a suprising amount +of work got done... + +

Arbitrary Arity Support

+ +I began using the Boost.Preprocessor +metaprogramming library to generate support for functions and member +functions of arbitrary arity, which was, to say the least, quite an +adventure. The feedback cycle resulting from my foray into +Boost.Preprocessor resulted in several improvements to the library, +most notably in its documentation. + +

+ +Boost.Python now supports calls of up to 17 arguments on most +compilers. Because most EDG-based compilers have dismal preprocessor +performance, I had to "manually" expand the metaprograms for +arities from zero to fifteen arguments, and EDG-based compilers with +__EDG_VERSION__ <= 245 only support 15 +arguments by default. If some crazy program finds a need for more than +the default arity support, users can increase the base support by +setting the BOOST_PYTHON_MAX_ARITY preprocessor symbol. + +

New Callback Interface

+ +I mentioned in last month's report that I +wasn't pleased with the interface for the interface for calling into +Python, so now it has been redesigned. The new interface is outlined +in this +message (though the GCC 2.95.3 bugs have been fixed). + +

Call Policies for Constructors

+ +On April 2nd, I announced +support for the use of call policies with constructors. + +

Real Users, Real Bugs

+ +At least two people outside of Kull began actually using Boost.Python +v2 in earnest this month. Peter Bienstman and Pearu Pearson both +provided valuable real-world bug reports that helped me to improve the +library's robustness. + +

New Insights

+ +Answering some of Pearu's questions about explicitly converting +objects between Python and C++ actually led me to a new understanding +of the role of the current conversion facilities. In Boost.Python v1, +all conversions between Python and C++ were handled by a single family +of functions, called to_python() and +from_python(). Since the primary role of Boost.Python is +to wrap C++ functions in Python, I used these names for the first kind +of converters I needed: those that extract C++ objects to be used as +function arguments and which C++ function return values to +Python. The better-considered approach in Boost.Python v2 uses a +completely different mechanism for conversions used when calling +Python from C++, as in wrapped virtual function implementations. I +usually think of this as a "callback", as in "calling +back into Python", and I named the converters used in callbacks +accordingly: to_python_callback and +from_python_callback. However, as it turns out, the +behavior of the "callback" converters is the appropriate one +for users who want to explicitly extract a C++ value from a Python +object, or create a Python object from a C++ value. The upshot is that +it probably makes sense to change the name of the existing to_python and +from_python so those names are available for the +user-friendly explicit converters. + +

+Another +of Pearu's questions pushes momentum further in the direction of a +more-sophisticated overloading mechanism than the current +simple-minded "first match" approach, as I suggested last month. + +

Boost.Python V1 Maintenance

+ +As much as I'm looking forward to retiring Boost.Python v1, a +significant amount of effort has been being spent dealing with support +problems; the saying that code rots when left alone is true, and +Boost.Python is no exception. Eventually it became obvious to me that +we were going to have to invest some effort in keeping V1 healthy +while working on V2. Ralf and I have expanded support for various +compilers and stabilized the V1 codebase considerably. We discarded +the obsolete Visual Studio projects which were causing so much +confusion. Still to do before the next Boost release: +
    +
  1. Update the build/test documentation with detailed instructions for +configuring various toolsets. +
  2. Provide some links to Boost.Python v2 to let people know what's +coming. +
+ + +

What's Missing

+ +Last month I announced that I would implement the following which are +not yet complete: +
    +
  1. Document all implemented features +
  2. Implement conversions for char types. This is +implemented but not tested, so we have to assume it doesn't work. +
+ +These are my first priority for this month (especially the +documentation). + +

Revised + + 13 November, 2002 + +

+

© Copyright Dave Abrahams + 2002.

+ + diff --git a/libs/python/doc/v2/CallPolicies.html b/libs/python/doc/v2/CallPolicies.html new file mode 100644 index 0000000000..06384a23d9 --- /dev/null +++ b/libs/python/doc/v2/CallPolicies.html @@ -0,0 +1,165 @@ + + + + + + + + + + + + Boost.Python - CallPolicies Concept + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

CallPolicies Concept

+
+
+ +
+
Introduction
+ +
CallPolicies Composition
+ +
Concept Requirements
+ +
+
+
CallPolicies Concept
+
+
+
+ +

Introduction

+ +

Models of the CallPolicies concept are used to specialize the behavior + of Python callable objects generated by Boost.Python to wrapped C++ + objects like function and member function pointers, providing three + behaviors:

+ +
    +
  1. precall - Python argument tuple management before the + wrapped object is invoked
  2. + +
  3. result_converter - C++ return value handling
  4. + +
  5. postcall - Python argument tuple and result management + after the wrapped object is invoked
  6. +
  7. extract_return_type - metafunction for extracting the return type from a given signature type sequence
  8. +
+ +

CallPolicies Composition

+ In order to allow the use of multiple models of CallPolicies in the same + callable object, Boost.Python's CallPolicies class templates provide a + chaining interface which allows them to be recursively composed. This + interface takes the form of an optional template parameter, + Base which defaults to default_call_policies. + By convention, the precall function of the Base + is invoked after the precall function supplied by the + outer template, and the postcall function of the + Base is invoked before the postcall + function of the outer template. If a result_converter is + supplied by the outer template, it replaces any + result_converter supplied by the Base. For an + example, see return_internal_reference. + + +

Concept Requirements

+ +

CallPolicies Concept

+ +

In the table below, x denotes an object whose type + P is a model of CallPolicies, a + denotes a PyObject* pointing to a Python argument tuple + object, and r denotes a PyObject* + referring to a "preliminary" result object.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeResult/Semantics
x.precall(a)convertible to boolreturns false and PyErr_Occurred() != 0 + upon failure, true otherwise.
P::result_converterA model of ResultConverterGenerator.An MPL unary Metafunction + Class used produce the "preliminary" result object.
x.postcall(a, r)convertible to PyObject*0 0 and PyErr_Occurred() != 0 + upon failure. Must "conserve references" even in the event of an + exception. In other words, if r is not returned, its + reference count must be decremented; if another existing object is + returned, its reference count must be incremented.
P::extract_return_typeA model of Metafunction.An MPL unary Metafunction used extract the return type from a given signature. By default it is derived from mpl::front.
+ Models of CallPolicies are required to be CopyConstructible. +
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ +

Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose.

+ + + diff --git a/libs/python/doc/v2/Dereferenceable.html b/libs/python/doc/v2/Dereferenceable.html new file mode 100644 index 0000000000..f7c53fd237 --- /dev/null +++ b/libs/python/doc/v2/Dereferenceable.html @@ -0,0 +1,74 @@ + + + + + + + +Boost.Python - Dereferenceable Concept + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+

Dereferenceable Concept

+
+
+
+
Introduction
+
Concept Requirements
+
+
Dereferenceable Concept
+
+
+ +

Introduction

+ +

Instances of a Dereferenceable type can be used like a pointer to access an lvalue. + +

Concept Requirements

+

Dereferenceable Concept

+ +

In the table below, T is a model of +Dereferenceable, and x denotes an object of +type T. In addition, all pointers are Dereferenceable. + + + + + + + + + + + + + + +
ExpressionResultOperational Semantics
get_pointer(x)convertible to pointee<T>::type* + &*x, or a null pointer +
+ +


+

Revised + + 18 December, 2003 + +

+

© Copyright Dave + Abrahams 2002-2003. + +

Permission to copy, use, modify, sell + and distribute this software is granted provided this copyright notice appears + in all copies. This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. + + diff --git a/libs/python/doc/v2/Extractor.html b/libs/python/doc/v2/Extractor.html new file mode 100644 index 0000000000..441ca38b39 --- /dev/null +++ b/libs/python/doc/v2/Extractor.html @@ -0,0 +1,96 @@ + + + + + + + +Boost.Python - Extractor Concept + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+

Extractor Concept

+
+


+
+
Introduction
+
Concept Requirements
+
+
Extractor Concept
+
+
Notes
+
+ +

Introduction

+ +

An Extractor is a class which Boost.Python can use to extract C++ +objects from Python objects, and is typically used by facilities that +define from_python conversions for +"traditional" Python extension types. + +

Concept Requirements

+

Extractor Concept

+ +

In the table below, X denotes a model of +Extractor and a denotes an instance of a Python +object type. + + + + + + + + + + + + + + + + + + +
ExpressionTypeSemantics
X::execute(a)non-void + Returns the C++ object being extracted. The + execute function must not be overloaded. +
&a.ob_type + PyTypeObject** + Points to the ob_type field of an object which is + layout-compatible with PyObject +
+ +

Notes

+ +Informally, an Extractor's execute member must be a +non-overloaded static function whose single argument is a Python +object type. Acceptable Python object types include those publicly (and +unambiguously) derived from PyObject, and POD types which +are layout-compatible with PyObject. + +
+

Revised + + 13 November, 2002 + +

+

© Copyright Dave + Abrahams 2002. + +

Permission to copy, use, modify, sell + and distribute this software is granted provided this copyright notice appears + in all copies. This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. + + diff --git a/libs/python/doc/v2/HolderGenerator.html b/libs/python/doc/v2/HolderGenerator.html new file mode 100644 index 0000000000..58b4265af8 --- /dev/null +++ b/libs/python/doc/v2/HolderGenerator.html @@ -0,0 +1,74 @@ + + + + + + + +Boost.Python - Holder Concept + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+

HolderGenerator Concept

+
+


+
+
Introduction
+
Concept Requirements
+
+
HolderGenerator Concept
+
+
+ +

Introduction

+ +

A HolderGenerator is a unary metafunction class which returns types +suitable for holding instances of its argument in a wrapped C++ class +instance. + +

Concept Requirements

+

HolderGenerator Concept

+ +

In the table below, G denotes an type which +models HolderGenerator, and X denotes a class +type. + + + + + + + + + + + +
ExpressionRequirements
G::apply<X>::typeA concrete subclass of instance_holder + which can hold objects of type X. +
+ +


+

Revised + + 13 November, 2002 + +

+

© Copyright Dave + Abrahams 2002. + +

Permission to copy, use, modify, sell + and distribute this software is granted provided this copyright notice appears + in all copies. This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. + + diff --git a/libs/python/doc/v2/Jun2002.html b/libs/python/doc/v2/Jun2002.html new file mode 100644 index 0000000000..db1fc25c62 --- /dev/null +++ b/libs/python/doc/v2/Jun2002.html @@ -0,0 +1,229 @@ + + + + + + + +Boost.Python - June 2002 Progress Report + + + + + + + +
+

+

+
+

Boost.Python

+

June 2002 Progress Report

+
+


+

Contents

+
+
Introduction
+
handle<T>
+
object
+
+
object operators
+
object conversions
+
+
list
+
Numerics
+
Community
+
What's Next
+
+ +

Introduction

+ +July was mostly focused on allowing expressive manipulation of +individual Python objects, or what Ralf Grosse-Kunstleve calls +"Writing Python in C++". The work began with this posting, +which outlines the issues and intention. + +

handle<T>

+ +The most basic element needed was a replacement for the +reference<> class template and the +ref typedef from Boost.Python v1, a simple smart +pointer to a Python object. The old v1 typedef +"ref" (for +reference<PyObject>) had to be retired because I +thought it would be too confusing given the importance of boost::ref() to this +library. I began a discussionof +possible names, and it was eventually decided +to rename reference to handle and supply a +default argument so that ref could be spelled +handle<> without an additional typedef. There +were also some interface changes to make it safer and more-efficient +to interface with the raw +PyObject*s forced on us by Python's 'C' API. A +discussion of those protocols can be found here. + +

object

+ +It is intended that users will seldom need or want to work with +handle<>; its major distinguishing features are +that it gives direct access to the underlying object representation +through operator* and operator->, and +that can be NULL, both sources of danger. Instead the +library provides a class called object, which +encapsulates a valid Python object and provides a similar interface to +Python's. + +

object operators

+ +The first challenge was to provide support for object manipulations +using a Python-like syntax, mostly in the form of operator overloads: + + + + + + + + + + + + + +
Python C++ + +
y = x.foo y = x.attr("foo"); +
x.foo = 1 x.attr("foo") = 1; + +
y = x[z] y = x[z]; +
x[z] = 1 x[z] = 1; + +
y = x[3:-1] y = x.slice(3,-1); + +
y = x[3:] y = x.slice(3,_); + +
y = x[:-2] y = x.slice(_,-2); + +
z = x(1, y) z = x(1, y); +
z = x.f(1, y) z = x.attr("f")(1, y); + +
not x !x + +
x and y x and y +
+ +I'm still a unsatisfied with the interface for attribute access. There +original proposal used a syntax like this one: +
+y = x._("foo"); 
+x._("foo") = 1; 
+
+ +which was only marginally better than what we've got. Niki Spahiev +then pointed +out a potential conflict with the macro which GNU Gettext suggests +people define. This unfortunate state of affairs forced us into using +attr instead. I'd still like to find a better interface, +but the lack of overloadable C++ operators which aren't already used +in Python is an obstacle. The comma operator is still a possibility, +but it has the wrong precedence: +
+y = x,"foo"    // error
+x,"foo" = 1;   // error
+
+y = (x,"foo"); // ok
+(x,"foo") = 1; // ok
+
+ +Well, I guess we could consider adding that to the interface without +removing attr(), to see how it plays out... + +

object conversions

+ +The object class also provided an opportunity to replace +Boost.Python v1's to_python() as a user-level +interface. Instead, object has a templated constructor +which can be used to convert any C++ object to Python using the same +underlying mechanisms used for the arguments to call<>. + +

Incidentally, the implementation of operator and conversion support +for object uncovered an inordinate number of compiler bugs in our +targeted platforms. It was a lot more "interesting" than it +should have been. + +

list

+ +With object implemented, it was time to begin replacing +the ad-hoc implementations of list, string, +and dictionary supplied by Boost.Python v1 with something +more robust. I started with list as an example. Because +object already provides all of the requisite operators, +publicly deriving list from object seemed like a good +choice. The remaining issues were what do do about the one-argument +list constructor (which in Python attempts to convert its argument to +a list), and how to deal converting with list arguments +to wrapped functions. Some of the issues are laid out in this +thread. Ultimately, it was decided that list(x) +should do the same thing in C++ as in Python (conversion), while +list arguments should only match Python +lists (and list subclasses). The +implementation worked well, and provided a roadmap +for the protocol to be used for implementation of the other built-in +types. + +

Numerics

+ +Support for C++ long long and unsigned long +long +(and __int64 on MSVC) to/from python conversions was +added this month. We also improved handling of numeric overflows when +converting, e.g., a Python int to a type with a more limited range of +representation. + +

Community

+ + + +Deep thanks to all the Boost.Python contributors! This project +wouldn't be possible without your participation. + +

What's Next

+ +As I write this we are already well into the month of July, so I +suggest you consult the Mailing +List Archive if you want to know what's been happening. Otherwise +you'll just have to wait till next month (hopefully the beginning). + +

Revised + + 13 November, 2002 + +

+

© Copyright Dave Abrahams + 2002.

+ + diff --git a/libs/python/doc/v2/Mar2002.html b/libs/python/doc/v2/Mar2002.html new file mode 100644 index 0000000000..97444d2290 --- /dev/null +++ b/libs/python/doc/v2/Mar2002.html @@ -0,0 +1,237 @@ + + + + + + + +Boost.Python - March 2002 Progress Report + + + + + + + +
+

+

+
+

Boost.Python

+

March 2002 Progress Report

+
+
+

Contents

+
+
Accomplishments
+
+
Calling Python from C++
+
Virtual Functions
+
Abstract Classes
+
C++ Implicit Conversions
+
C++ Data Members
+
Miscellaneous
+
+ +
The Near future
+ +
Notes
+ +
+ +

Accomplishments

+ +March was mostly devoted to the reimplementation of features from +Boost.Python v1, and some new features. Re-examination of the features +from Boost.Python v1 allowed me to make significant improvements. + +

Calling Python from C++

+ +The ability to call Python from C++ is crucial for virtual function +support. Implementing this feature well for V2 proved to be more +interesting than I expected. You can review most of the relevant +design decisions +here. + +

+One point which isn't emphasized in that document is that there +are subtle differences in the way from_python conversions +work when used for C++ function arguments and Python function return +values. In particular, while T const& arguments may +invoke rvalue converters, a reference-to-const return value requires +an lvalue converter, since a temporary conversion result would leave +the returned reference dangling. + +

I'm not particularly pleased with the current callback interface, +since it usually results in constructs like: +

+return returning<X&>::call(f, obj);
+
+However, I think the following may be possible and I plan to investigate: +
+return apply<X&>(f, obj);
+
+I'm open to suggestion for better names (and syntaxes)! + +

Virtual Functions

+ +Once Python callbacks were implemented, it was just a short step to +implementing virtual functions. Python extension class exposing a C++ +class whose virtual functions are overridable in Python must actually +hold a C++ instance of a class derived from the one exposed to +Python. Needing some way for users to specify that class, I added an +optional template argument to value_holder_generator and +pointer_holder_generator<> to specify the class +actually held. This move began to put pressure on the +class_<> interface, since the need for the user to +produce complicated instantations of +class_<> was increased: + +
+class<Foo, bases<>, value_holder_generator<Foo_callback> >("Foo")
+.def("hello", &Foo::hello)
+...
+
+ +

Abstract Classes

+ +Normally when a C++ class is exposed to Python, the library registers +a conversion function which allows users to wrap functions returning +values of that type. Naturally, these return values are temporaries, +so the conversion function must make a copy in some +dynamically-allocated storage (a "holder") which is managed +by the corresponding Python object. + +

Unfortunately, in the case of abstract classes (and other types +without a publicly-accessible copy constructor), instantiating this +conversion function causes a compilation error. In order to support +non-copyable classes, there had to be some way to prevent the library +from trying to instantiate the conversion function. The only practical +approach I could think of was to add an additional template parameter +to the class_<> interface. When the number of +template parameters with useful defaults begins to grow, it is often +hard to choose an order which allows users to take advantage of the +defaults. + +

+ +This was the straw that broke the +class_<> interface's back and caused the redesign +whose outcome is detailed here. +The approach allows the user to supply the optional parameters in an +arbitrary order. It was inspired by the use of named +template parameters in the Boost Iterator Adaptor +Library, though in this case it is possible to deduce the meaning +of the template parameters entirely from their type properties, +resulting in a simpler interface. Although the move from a +policy-based design to what resembles a configuration DSL usually +implies a loss of flexibility, in this case I think any costs are far +outweighed by the advantages. + +

Note: working around the limitations of the various compilers I'm +supporting was non-trivial, and resulted in a few messy implementation +details. It might be a good idea to switch to a more-straightforward +approach once Metrowerks CodeWarrior Pro8 is released. + +

C++ Implicit Conversions

+ +Support for C++ implicit conversion involves creating +from_python converters for a type U which in +turn use from_python converters registered for a type +T where there exists a implicit conversion from +T to U. The current implementation is +subject to two inefficiencies: +
    + +
  1. Because an rvalue from_python converter produces two +pieces of data (a function and a void*) from its +convertible() function, we end up calling the function +for T twice: once when the converter is looked up in the +registry, and again when the conversion is actually performed. + +
  2. A vector is used to mark the "visited" converters, preventing +infinite recursion as T to +U and U to T converters +continually search through one-another. + +
+ +I consider the former to be a minor issue. The second may or may not +prove to be computationally significant, but I believe that +architecturally, it points toward a need for more sophisticated +overload resolution. It may be that we want CLOS-style multimethod +dispatching along with C++ style rules that prevent more than one +implicit conversion per argument. + +

C++ Data Members

+ +To supply the ability to directly access data members, I was able to +hijack the new Python property +type. I had hoped that I would also be able to re-use the work of make_function to create callable python +objects from C++ functions which access a data member of a given +class. C++ facilities for specifying data member pointer non-type +template arguments require the user to explicitly specify the type of +the data member and this under-utilized feature is also not +well-implemented on all compilers, so passing the member pointer as a +runtime value is the only practical approach. The upshot is that any +such entity would actually have to be a function object, and I +haven't implemented automatic wrapping of C++ callable function +objects yet, so there is less re-use in the implementation than I'd +like. I hope to implement callable object wrapping and refactor this +code one day. I also hope to implement static data member support, +for which Python's property will not be an appropriate descriptor. + +

Miscellaneous

+
    +
  • Moved args<> and bases<> from unnamed namespace to boost::python in their own header files. +
  • Convert NULL pointers returned from wrapped C++ functions to None. +
  • Improved some compile-time error checks. +
  • Eliminated boost/python/detail/eval.hpp in favor of +more-general boost/mpl/apply.hpp. +
  • General code cleanup and refactoring. +
  • Works with Microsoft Visual C++ 7.0 +
  • Warning suppression for many compilers +
  • Elegant interface design for exporting enum types. +
+
+ +

The Near Future

+ +Before April 15th I plan to +
    +
  1. Document all implemented features +
  2. Implement a CallPolicy interface for constructors of wrapped +classes +
  3. Implement conversions for char types. +
  4. Implement automated code generation for all headers containing +families of overloaded functions to handle arbitrary arity. +
+ +I also hope to implement a mechanism for generating conversions +between arbitrary Python sequences and C++ containers, if time permits +(and others haven't already done it)! + +

Notes

+ +The older version of KCC used by Kull is generating lots of warnings +about a construct I use to instantiate static members of various class +templates. I'm thinking of moving to an idiom which uses a function +template to suppress it, but worry about bloating the size of debug +builds. Since KCC users may be moving to GCC, I'm not sure that it's +worth doing anything about it. + +

Revised + + 13 November, 2002 + +

+

© Copyright Dave Abrahams + 2002.

+ + diff --git a/libs/python/doc/v2/May2002.html b/libs/python/doc/v2/May2002.html new file mode 100644 index 0000000000..5e5b6aaa4b --- /dev/null +++ b/libs/python/doc/v2/May2002.html @@ -0,0 +1,311 @@ + + + + + + + +Boost.Python - May 2002 Progress Report + + + + + + + +
+

+

+
+

Boost.Python

+

May 2002 Progress Report

+
+
+

Contents

+
+
Introduction
+
New Features
+
+
Shared Library Support for AIX
+
Class Enhancements
+
+
Operators
+
Iterators
+
Properties
+
setattr
+
__module__ Attribute
+
+
back_reference
+
+ +
Documentation
+
Miscellaneous
+
+
Converters
+
Checkins Mailing List
+
Shared Libraries
+
+ +
What's Next
+
+ +

Introduction

+ +Aside from library development, work on Boost.Python in May was +focused on reducing the support burden. In recent weeks, responding to +requests for support, espcially surrounding building the library, had +begun to impede progress on development. There was a major push to +release a stable 1.28.0 of Boost, including documentation of Boost.Build and specific +instructions for building Boost.Python +v1. The documentation for Boost.Python v2 was also updated as +described here. + +

New Features

+ +

Shared Library Support for AIX

+ + The Kull group required the ability to build and test Boost.Python + extensions on AIX, a platform with "creatively designed" + shared library semantics. Making this work was a multi-pronged + effort, involving changes to Boost.Build and some great research by + Martin Casado which uncovered the key mechanism required to allow + shared libraries to use functions from the Python executable. The + current solution used in Boost.Build relies on a Python + Script as part of the build process. This is not a problem for + Boost.Python, as Python will be available. However, the commands + issued by the script are so simple that a 100%-pure-Boost.Jam + solution is surely possible. Linking on AIX is sufficiently + interesting to have skewed the Boost.Python development schedule a + bit. + +

Class Enhancements

+ +

Operators

+ +Support for exposing C++ operators and functions as the corresponding +Python special methods was added. Thinking that the Boost.Python +v1 interface was a little too esoteric (especially the use of +left_operand<...>/right_operand<...> for +asymmetric operands), I introduced a simple form of expression +templates which allow users to simply write the expressions that +should be wrapped, as in this example. + +

Iterators

+ +Python iterator support as required by the Kull project resulted in a +highly flexible interface allowing: + +
+ +
Direct exposure of a class' begin() and +end() functions: + +
+    ...
+    .def("__iter__", iterator<list_int>())
+
+
+ +
Creation of iterators from member functions... +
+    ...
+    .def("__iter__"
+         , range(&my_class::x_begin, &my_class::x_end))
+    )
+
+
+ +
...and member data: +
+    ...
+    .def("__iter__"
+         , range(&std::pair<char*,char*>::first, &std::pair<char*,char*>::second))
+    )
+
+
+ +
The ability to specify CallPolicies, e.g. to prevent copying of +heavyweight values: + +
+    ...
+    .def("__iter__", 
+         , range<return_value_policy<copy_non_const_reference> >(
+               &my_sequence<heavy>::begin
+             , &my_sequence<heavy>::end))
+
+
+ +
+ +

Properties

+ +The Kull iteration interfaces also required the ability to iterate +over a sequence specified by an instance's attribute: +
+>>> f = field()
+>>> for e in f.elements:
+...     print e,
+
+ +This forced the exposure of the property + interface used internally to implement the data member exposure + facility described in March. Properties are an + incredibly useful idiom, so it's good to be able to provide them + at little new development cost. + +

setattr

+ +class_<> acquired a setattr member +function which allows users to easily add new Python objects as class +attributes. + +

__module__ Attribute

+ +Ralf Grosse-Kunstleve has been working on pickling support for v2. To +make it work correctly, he had to make sure that a class' +__module__ attribute was set correctly. + +

back_reference

+ +The new back_reference<T> template can be used as a +function parameter when the user needs access to both a T +argument and to the Python object which manages it. The function will +only match in the overload resolution process if it would match the +same function signature with T substituted for +back_reference<T>. This feature is not yet +documented. + +

Documentation

+ +In a major effort to prepare Boost.Python v2 to replace v1, many pages +of new reference documentation were added: + +
+ +
+
CallPolicies.html
+
Dereferenceable.html
+
Extractor.html
+
HolderGenerator.html
+
ResultConverter.html
+
call_method.html
+
callbacks.html
+
data_members.html
+
has_back_reference.html
+
implicit.html
+
instance_holder.html
+
operators.html
+
ptr.html
+
type_id.html
+
with_custodian_and_ward.html
+
+ +
+Major updates were made to the following pages: + + +
+
+
call.html
updated
+
class.html
+
reference.html
+
+
+ + As usual, careful documentation forces one to consider the + interface again, and there were many interface changes + associated with this effort, including the elevation of the + following components from implementation detail to + first-class library citizen: + +
+
+
type_id.hpp
+
pointee.hpp
+
lvalue_from_pytype.hpp
+ +
+ +

Miscellaneous

+ +

Converters

+ +It appears that the world of C++ <==> Python conversion rules is +an endlessly-rich area of exploration. Completing the conversions for +char and char const* types, as described at +the end of April's report, +uncovered some interesting new shades to the problem. It turns out to +be worth distinguishing mutable and immutable lvalue conversions, +because despite the fact that Python doesn't understand +const, it does understand immutability (c.f. Python +strings, which expose an immutable char pointer). It is +also worth recognizing types which represent lvalue sequences, +to prevent Python "foobar" from being silently +truncated to C++ 'f'. More details on this insight can be +found in the mailing list +archive. I don't plan to do anything about this immediately, but I +do think it's the right direction to go in the long run. + +

Checkins Mailing List

+ +In order to better coordinate changes made by multiple developers, I +enabled syncmail +for the Boost.Python CVS trees, and established an associated mailing +list. Subscribe to this list to receive notices of each new +checkin. + +

Shared Libraries

+ +Beyond the vagaries of dynamic linking on AIX, I have been +participating in a more-general discussion of dynamic linking for +C++. Needless to say, C++ dynamic linking is of critical importance to +Boost.Python: all extension modules are normally built as shared +libraries, and Boost.Python extension modules share a common library +as well. + +In fact, there are at least two separate conversations. One +in the C++ standard extensions mailing list concerns what can be +standardized for C++ and shared libraries; the other, mostly on the gcc mailing list, concerns the +behavior of GCC on Posix/ELF platforms. + +Some of the GCC threads are here: + +
+http://gcc.gnu.org/ml/gcc/2002-05/msg02002.html
+http://gcc.gnu.org/ml/gcc/2002-05/msg02945.html
+http://gcc.gnu.org/ml/gcc/2002-05/msg01758.html +
+ +

What's Next

+ +Development is focused on what's needed to be able to retire +Boost.Python v1. At the moment, that means deciding the user-friendly +interfaces for to_/from_python conversion, and formally exposing the +Python object smart pointers and object wrapper classes. Quite a few +questions have also been showing up recently about how to embed Python +with Boost.Python, and how to link with it statically; the solutions +to these issues will probably have to be formalized before long. + +

Revised + + 13 November, 2002 + +

+

© Copyright Dave Abrahams + 2002.

+ + diff --git a/libs/python/doc/v2/ObjectWrapper.html b/libs/python/doc/v2/ObjectWrapper.html new file mode 100644 index 0000000000..7962e69fa5 --- /dev/null +++ b/libs/python/doc/v2/ObjectWrapper.html @@ -0,0 +1,153 @@ + + + + + + + + + + + + Boost.Python - ObjectWrapper Concept + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

ObjectWrapper and TypeWrapper Concepts

+
+
+ +
+
Introduction
+ +
Concept Requirements
+ +
+
+
ObjectWrapper Concept
+ +
TypeWrapper Concept
+
+
+ +
Caveat
+
+ +

Introduction

+ +

This page defines two concepts used to describe classes which manage a + Python objects, and which are intended to support usage with a + Python-like syntax.

+ +

Concept Requirements

+ +

ObjectWrapper Concept

+ Models of the ObjectWrapper concept have object as a publicly-accessible base class, + and are used to supply special construction behavior and/or additional + convenient functionality through (often templated) member functions. + Except when the return type R is itself an TypeWrapper, a member function invocation of + the form +
+x.some_function(a1, a2,...an)
+
+ always has semantics equivalent to: +
+extract<R>(x.attr("some_function")(object(a1), object(a2),...object(an)))()
+
+ When the R is an TypeWrapper, the result type may be + constructed by taking direct posession of: +
+x.attr("some_function")(object(a1), object(a2),...object(an)).ptr()
+
+ [see caveat below] + +

TypeWrapper Concept

+ TypeWrapper is a refinement of ObjectWrapper which is associated with a + particular Python type X. For a given TypeWrapper + T, a valid constructor expression +
+T(a1, a2,...an)
+
+ builds a new T object managing the result of invoking + X with arguments corresponding to +
+object(a1), object(a2),...object(an)
+
+ +When used as arguments to wrapped C++ functions, or as the template +parameter to extract<>, only +instances of the associated Python type will be considered a match. + +

Caveat

+ The upshot of the special member function invocation rules when the + return type is a TypeWrapper is that it is possible for the returned + object to manage a Python object of an inappropriate type. This is not + usually a serious problem; the worst-case result is that errors will be + detected at runtime a little later than they might otherwise be. For an + example of how this can occur, note that the dict member function items + returns an object of type list. Now suppose the user defines this + dict subclass in Python: +
+>>> class mydict(dict):
+...     def items(self):
+...         return tuple(dict.items(self)) # return a tuple
+
+ Since an instance of mydict is also an instance of + dict, when used as an argument to a wrapped C++ function, + boost::python::dict can + accept objects of Python type mydict. Invoking + items() on this object can result in an instance of boost::python::list which actually + holds a Python tuple. Subsequent attempts to use list methods (e.g. + append, or any other mutating operation) on this object will + raise the same exception that would occur if you tried to do it from + Python. +
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/ResultConverter.html b/libs/python/doc/v2/ResultConverter.html new file mode 100644 index 0000000000..be53a9b974 --- /dev/null +++ b/libs/python/doc/v2/ResultConverter.html @@ -0,0 +1,124 @@ + + + + + + + + + +Boost.Python - ResultConverter Concept + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+

ResultConverter Concept

+
+
+
+
Introduction
+
Concept Requirements
+
+
+
ResultConverter Concept
+
ResultConverterGenerator Concept
+
+
+
+ +

Introduction

+ +

A ResultConverter for a type T is a type whose +instances can be used to convert C++ return values of type +T to_python. A ResultConverterGenerator is +an MPL unary metafunction class which, given the return type of a C++ +function, returns a ResultConverter for that type. ResultConverters in +Boost.Python generally inspect library's registry of converters to +find a suitable converter, but converters which don't use the registry +are also possible. + +

Concept Requirements

+

ResultConverter Concept

+ +

In the table below, C denotes a ResultConverter +type for a type R , c denotes +an object of type C , and r +denotes an object of type R. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionTypeSemantics
C c; + Constructs a C object. +
c.convertible()convertible to boolfalse iff no conversion from any R value + to a Python object is possible.
c(r)convertible to PyObject*A pointer to a Python object corresponding to r, + or 0 iff r could not be converted + to_python, in which case PyErr_Occurred + should return non-zero.
c.get_pytype()PyTypeObject const*A pointer to a Python Type object corresponding to result of the conversion, + or 0. Used for documentation generation. If 0 is returned + the generated type in the documentation will be object .
+ +

ResultConverterGenerator Concept

+

In the table below, G denotes a +ResultConverterGenerator type and R denotes a possible +C++ function return type. + + + + + + + + + +
ExpressionRequirements
G::apply<R>::typeA ResultConverter type for R.
+ +


+

Revised + + 09 May, 2002 + +

+

© Copyright Dave + Abrahams 2002. + +

Permission to copy, use, modify, sell + and distribute this software is granted provided this copyright notice appears + in all copies. This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. + + diff --git a/libs/python/doc/v2/acknowledgments.html b/libs/python/doc/v2/acknowledgments.html new file mode 100644 index 0000000000..28f1b1dbde --- /dev/null +++ b/libs/python/doc/v2/acknowledgments.html @@ -0,0 +1,135 @@ + + + + + + + + + + + + Boost.Python - Acknowledgments + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Acknowledgments

+
+


+ +

Dave Abrahams is + the architect, designer, and implementor of Boost.Python.

+ +

Brett Calcott + contributed and maintains the Visual Studio project files and + documentation.

+ +

Gottfried + Ganauge supplied support for opaque pointer conversions, + complete with documentation and a regression test (and I didn't + even have to ask him for those)! + +

Joel de Guzman implemented the default + argument support and wrote the excellent tutorial documentation.

+ +

Ralf W. + Grosse-Kunstleve implemented the pickle + support, and has enthusiastically supported the library since its + birth, contributing to design decisions and providing invaluable + real-world insight into user requirements. Ralf has written some extensions for converting C++ containers that I + hope will be incorporated into the library soon. He also implemented the + cross-module support in the first version of Boost.Python. More + importantly, Ralf makes sure nobody forgets the near-perfect synergy of + C++ and Python for solving the problems of large-scale software + construction.

+ +

Aleksey Gurtovoy + wrote an incredible C++ Template + Metaprogramming Library which allows Boost.Python to perform much of + its compile-time magic. In addition, Aleksey very generously contributed + his time and deep knowledge of the quirks of various buggy compilers to + help us get around problems at crucial moments.

+ +

Paul Mensonides, + building on the work Vesa + Karvonen, wrote a similarly amazing Preprocessor Metaprogramming + Library, and generously contributed the time and expertise to get it + working in the Boost.Python library, rewriting much of Boost.Python to + use the new preproccessor metaprogramming constructs and helping us to + work around buggy and slow C++ preprocessors.

+ +

Bruno da Silva de + Oliveira contributed the ingenious Pyste ("Pie-Steh") + code generator. + +

Nikolay Mladenov contributed + staticmethod support.

+ +

Martin Casado solved some sticky problems which allow us to build the + Boost.Python shared library for AIX's crazy dynamic linking model.

+ +

Achim Domma contributed some + of the Object Wrappers and + HTML templates for this documentation. Dave Hawkes contributed + inspiration for the use of the scope class to simplify module + definition syntax. Pearu Pearson wrote some of the test cases that are in + the current test suite.

+ +

The development of this version of Boost.Python was funded in part by + the Lawrence Livermore National + Laboratories and by the Computational + Crystallography Initiative at Lawrence Berkeley National + Laboratories.

+ +

Ullrich + Koethe had independently developed a similar system. When he + discovered Boost.Python v1, he generously contributed countless hours of + coding and much insight into improving it. He is responsible for an early + version of the support for function overloading and wrote the support for + reflecting C++ inheritance relationships. He has helped to improve + error-reporting from both Python and C++ (we hope to do as well in v2 + again soon), and has designed the original support for exposing numeric + operators, including a way to avoid explicit coercion by means of + overloading.

+ +

The members of the boost mailing list and the Python community + supplied invaluable early feedback. In particular, Ron Clarke, Mark + Evans, Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott + took the brave step of trying to use Boost.Python while it was still in + early stages of development.

+ +

The first version of Boost.Python would not have been possible without + the support of Dragon Systems, which supported its development and + release as a Boost library.

+
+ +

Revised + + 26 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/args.html b/libs/python/doc/v2/args.html new file mode 100644 index 0000000000..e04720b7e5 --- /dev/null +++ b/libs/python/doc/v2/args.html @@ -0,0 +1,199 @@ + + + + + + + + + + + + Boost.Python - <boost/python/args.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/args.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
keyword-expressions
+ +
Classes
+ +
+
+
class arg
+ +
+
+
class arg + synopsis
+ +
class arg + constructor
+ +
class arg template + operator =
+
+
+
+
+ +
Keyword-expression + operator ,
+ +
Functions (deprecated)
+ +
+
+
args(...)
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

Supplies a family of overloaded functions for specifying argument + keywords for wrapped C++ functions.

+ +

keyword-expressions

+ +

A keyword-expression results in an object which holds a + sequence of ntbses, and whose type + encodes the number of keywords specified. The keyword-expression + may contain default values for some or all of the keywords it holds

+ +

Classes

+ +

class arg;

+ +

The objects of class arg are keyword-expressions holding one keyword ( + size one )

+ +

Class arg synopsis

+
+namespace boost { namespace python
+{
+        struct arg 
+        {
+          template <class T>
+                  arg &operator = (T const &value);
+          explicit arg (char const *name){elements[0].name = name;}
+        };
+
+}}
+
+ +

Class arg constructor

+
+arg(char const* name);
+
+ +
+
Requires: The argument must be a ntbs.
+ +
Effects: Constructs an arg object holding a + keyword with name name.
+
+ +

Class arg operator =

+
+template <class T> arg &operator = (T const &value);
+
+ +
+
Requires: The argument must convertible to python.
+ +
Effects: Assigns default value for the keyword.
+ +
Returns: Reference to this.
+
+ +

Keyword-expression + operator ,

+
+      keyword-expression operator , (keyword-expression, const arg &kw) const
+      keyword-expression operator , (keyword-expression, const char *name) const;
+
+ +
+
Requires: The argument name must be a ntbs.
+ +
Effects: Extends the keyword-expression argument with + one more keyword.
+ +
Returns: The extended keyword-expression.
+
+ +

Functions + (deprecated)

+ +

args(...)

+
+  unspecified1 args(char const*);
+    unspecified2 args(char const*, char const*);
+       .
+       .
+       .
+    unspecifiedN args(char const*, char const*, ... char const*);
+
+
+ +
+
Requires: Every argument must be a ntbs.
+ +
Returns: an object representing a keyword-expression encapsulating + the arguments passed.
+
+ +

Example

+
+#include <boost/python/def.hpp>
+using namespace boost::python;
+
+int f(double x, double y, double z=0.0, double w=1.0);
+
+BOOST_PYTHON_MODULE(xxx)
+{
+   def("f", f
+            , ( arg("x"), "y", arg("z")=0.0, arg("w")=1.0 ) 
+            );
+}
+
+ +

Revised 01 August, 2003

+ +

© Copyright Dave Abrahams 2002-2003.

+ + + diff --git a/libs/python/doc/v2/call.html b/libs/python/doc/v2/call.html new file mode 100644 index 0000000000..adba2b5fe8 --- /dev/null +++ b/libs/python/doc/v2/call.html @@ -0,0 +1,85 @@ + + + + + + + +Boost.Python - <call.hpp> + + + + + + + +
+

+

+
+

Boost.Python

+

Header <call.hpp>

+
+
+

Contents

+
+
Introduction
+
Functions
+
+
call
+
+ +
Example(s)
+ +
+
+

Introduction

+

+ <boost/python/call.hpp> defines the call family of overloaded function + templates, used to invoke Python callable objects from C++. + +

Functions

+
+template <class R, class A1, class A2, ... class An>
+R call(PyObject* callable, A1 const&, A2 const&, ... An const&)
+
+
+
Requires: R is a pointer type, reference + type, or a complete type with an accessible copy constructor
+ +
Effects: Invokes callable(a1, a2, ...an) in + Python, where a1...an are the arguments to + call(), converted to Python objects. +
Returns: The result of the Python call, converted to the C++ type R.
+ + +
Rationale: For a complete semantic description and + rationale, see this page. +
+
+ +

Example(s)

+ +The following C++ function applies a Python callable object to its two +arguments and returns the result. If a Python exception is raised or +the result can't be converted to a double, an exception +is thrown. + +
+double apply2(PyObject* func, double x, double y)
+{
+   return boost::python::call<double>(func, x, y);
+}
+
+ +

Revised + + 9 May, 2002 + +

+

© Copyright Dave Abrahams + 2002.

+ + diff --git a/libs/python/doc/v2/call_method.html b/libs/python/doc/v2/call_method.html new file mode 100644 index 0000000000..e54ffb26aa --- /dev/null +++ b/libs/python/doc/v2/call_method.html @@ -0,0 +1,161 @@ + + + + + + + + + + + + Boost.Python - <call_method.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <call_method.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
call_method
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

<boost/python/call_method.hpp> defines the call_method family of overloaded + function templates, used to invoke callable attributes of Python objects + from C++.

+ +

Functions

+
+template <class R, class A1, class A2, ... class An>
+R call_method(PyObject* self, char const* method, A1 const&, A2 const&, ... An const&)
+
+ +
+
Requires: R is a pointer type, reference type, + or a complete type with an accessible copy constructor
+ +
Effects: Invokes + self.method(a1, a2, ...an) in + Python, where a1...an are the + arguments to call_method(), converted to Python objects. + For a complete semantic description, see this + page.
+ +
Returns: The result of the Python call, converted to the C++ + type R.
+ +
Rationale: call_method is critical to + implementing C++ virtual functions which are overridable in Python, as + shown by the example below.
+
+ +

Example(s)

+ The following C++ illustrates the use of call_method in + wrapping a class with a virtual function that can be overridden in + Python: + +

C++ Module Definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/utility.hpp>
+#include <cstring>
+
+// class to be wrapped
+class Base
+{
+ public:
+   virtual char const* class_name() const { return "Base"; }
+   virtual ~Base();
+};
+
+bool is_base(Base* b)
+{
+   return !std::strcmp(b->class_name(), "Base");
+}
+
+// Wrapper code begins here
+using namespace boost::python;
+
+// Callback class
+class Base_callback : public Base
+{
+ public:
+   Base_callback(PyObject* self) : m_self(self) {}
+
+   char const* class_name() const { return call_method<char const*>(m_self, "class_name"); }
+   char const* Base_name() const { return Base::class_name(); }
+ private:
+   PyObject* const m_self;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(my_module)
+{
+    def("is_base", is_base);
+
+    class_<Base,Base_callback, noncopyable>("Base")
+        .def("class_name", &Base_callback::Base_name)
+        ;
+
+}
+
+ +

Python Code

+
+>>> from my_module import *
+>>> class Derived(Base):
+...    def __init__(self):
+...       Base.__init__(self)
+...    def class_name(self):
+...       return self.__class__.__name__
+...
+>>> is_base(Base()) # calls the class_name() method from C++
+1
+>>> is_base(Derived())
+0
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/callbacks.html b/libs/python/doc/v2/callbacks.html new file mode 100644 index 0000000000..4e91befadb --- /dev/null +++ b/libs/python/doc/v2/callbacks.html @@ -0,0 +1,254 @@ + + + + + + + + + + + + Boost.Python - Calling Python Functions and Methods + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Calling Python Functions and Methods

+
+
+ +

Contents

+ +
+
Introduction
+ +
Argument Handling
+ +
Result Handling
+ +
Rationale
+
+
+ +

Introduction

+ The simplest way to call a Python function from C++, given an object instance f + holding the function, is simply to invoke its function call operator. +
+f("tea", 4, 2) // In Python: f('tea', 4, 2)
+
+ And of course, a method of an object instance x can + be invoked by using the function-call operator of the corresponding + attribute: +
+x.attr("tea")(4, 2); // In Python: x.tea(4, 2)
+
+ +

If you don't have an object instance, Boost.Python + provides two families of function templates, call and call_method, for invoking + Python functions and methods respectively on PyObject*s. The + interface for calling a Python function object (or any Python callable + object) looks like:

+
+call<ResultType>(callable_object, a1, a2... aN);
+
+ Calling a method of a Python object is similarly easy: +
+call_method<ResultType>(self_object, "method-name", a1, a2... aN);
+
+ This comparitively low-level interface is the one you'll use when + implementing C++ virtual functions that can be overridden in Python. + +

Argument Handling

+ +

Arguments are converted to Python according to their type. By default, + the arguments a1...aN are copied into + new Python objects, but this behavior can be overridden by the use of + ptr() and ref():

+
+class X : boost::noncopyable
+{
+   ...
+};
+
+void apply(PyObject* callable, X& x)
+{
+   // Invoke callable, passing a Python object which holds a reference to x
+   boost::python::call<void>(callable, boost::ref(x));
+}
+
+ In the table below, x denotes the actual argument + object and cv denotes an optional + cv-qualification: "const", "volatile", + or "const volatile". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Argument TypeBehavior
T cv&
+ T cv
The Python argument is created by the same means used for the + return value of a wrapped C++ function returning T. When + T is a class type, that normally means *x + is copy-constructed into the new Python object.
T*If x == 0, the Python argument will be + None. + Otherwise, the Python argument is created by the same means used for + the return value of a wrapped C++ function returning T. + When T is a class type, that normally means + *x is copy-constructed into the new Python object.
boost::reference_wrapper<T>The Python argument contains a pointer to, rather than a copy of, + x.get(). Note: failure to ensure that no Python code + holds a reference to the resulting object beyond the lifetime of + *x.get() may result in a crash!
pointer_wrapper<T>If x.get() == 0, the Python argument will + be None. + Otherwise, the Python argument contains a pointer to, rather than a + copy of, *x.get(). Note: failure to ensure that no + Python code holds a reference to the resulting object beyond the + lifetime of *x.get() may result in a crash!
+ +

Result Handling

+ In general, call<ResultType>() and + call_method<ResultType>() return + ResultType by exploiting all lvalue and rvalue + from_python converters registered for ResultType and + returning a copy of the result. However, when ResultType is + a pointer or reference type, Boost.Python searches only for lvalue + converters. To prevent dangling pointers and references, an exception + will be thrown if the Python result object has only a single reference + count. + +

Rationale

+ In general, to get Python arguments corresponding to + a1...aN, a new Python object must be + created for each one; should the C++ object be copied into that Python + object, or should the Python object simply hold a reference/pointer to + the C++ object? In general, the latter approach is unsafe, since the + called function may store a reference to the Python object somewhere. If + the Python object is used after the C++ object is destroyed, we'll crash + Python. + +

In keeping with the philosophy that users on the Python side shouldn't + have to worry about crashing the interpreter, the default behavior is to + copy the C++ object, and to allow a non-copying behavior only if the user + writes boost::ref(a1) + instead of a1 directly. At least this way, the user doesn't get dangerous + behavior "by accident". It's also worth noting that the non-copying + ("by-reference") behavior is in general only available for class types, + and will fail at runtime with a Python exception if used otherwise[1].

+ +

However, pointer types present a problem: one approach is to refuse to + compile if any aN has pointer type: after all, a user can always pass + *aN to pass "by-value" or ref(*aN) to indicate + a pass-by-reference behavior. However, this creates a problem for the + expected null pointer to None conversion: it's illegal to + dereference a null pointer value.

+ +

The compromise I've settled on is this:

+ +
    +
  1. The default behavior is pass-by-value. If you pass a non-null + pointer, the pointee is copied into a new Python object; otherwise the + corresponding Python argument will be None.
  2. + +
  3. if you want by-reference behavior, use ptr(aN) if + aN is a pointer and ref(aN) otherwise. If a + null pointer is passed to ptr(aN), the corresponding + Python argument will be None.
  4. +
+ +

As for results, we have a similar problem: if ResultType + is allowed to be a pointer or reference type, the lifetime of the object + it refers to is probably being managed by a Python object. When that + Python object is destroyed, our pointer dangles. The problem is + particularly bad when the ResultType is char const* - the + corresponding Python String object is typically uniquely-referenced, + meaning that the pointer dangles as soon as call<char + const*>(...) returns.

+ +

The old Boost.Python v1 deals with this issue by refusing to compile + any uses of call<char const*>(), but this goes both + too far and not far enough. It goes too far because there are cases where + the owning Python string object survives beyond the call (just for + instance, when it's the name of a Python class), and it goes not far + enough because we might just as well have the same problem with a + returned pointer or reference of any other type.

+ +

In Boost.Python v2 this is dealt with by:

+ +
    +
  1. lifting the compile-time restriction on const char* callback + returns
  2. + +
  3. detecting the case when the reference count on the result Python + object is 1 and throwing an exception inside of + call<U>(...) when U is a pointer or + reference type.
  4. +
+ This should be acceptably safe because users have to explicitly specify a + pointer/reference for U in call<U>, and + they will be protected against dangles at runtime, at least long enough + to get out of the call<U>(...) invocation. +
+ [1] It would be possible to make it fail at compile-time + for non-class types such as int and char, but I'm not sure it's a good + idea to impose this restriction yet. + +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/callbacks.txt b/libs/python/doc/v2/callbacks.txt new file mode 100644 index 0000000000..2795680fd7 --- /dev/null +++ b/libs/python/doc/v2/callbacks.txt @@ -0,0 +1,92 @@ +.. Copyright David Abrahams 2006. 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) + +Here's the plan: + +I aim to provide an interface similar to that of Boost.Python v1's +callback<>::call(...) for dealing with callbacks. The interface will +look like: + + returning::call("method_name", self_object, a1, a2...); + +or + + returning::call(callable_object, a1, a2...); + +ARGUMENT HANDLING + +There is an issue concerning how to make Python objects from the +arguments a1...aN. A new Python object must be created; should the C++ +object be copied into that Python object, or should the Python object +simply hold a reference/pointer to the C++ object? In general, the +latter approach is unsafe, since the called function may store a +reference to the Python object somewhere. If the Python object is used +after the C++ object is destroyed, we'll crash Python. + +I plan to make the copying behavior the default, and to allow a +non-copying behavior if the user writes boost::ref(a1) instead of a1 +directly. At least this way, the user doesn't get dangerous behavior "by +accident". It's also worth noting that the non-copying ("by-reference") +behavior is in general only available for class types, and will fail at +runtime with a Python exception if used otherwise** + +However, pointer types present a problem: My first thought is to refuse +to compile if any aN has pointer type: after all, a user can always pass +*aN to pass "by-value" or ref(*aN) to indicate a pass-by-reference +behavior. However, this creates a problem for the expected NULL pointer +=> None conversion: it's illegal to dereference a null pointer value. + +We could use another construct, say "ptr(aN)", to deal with null +pointers, but then what does it mean? We know what it does when aN is +NULL, but it might either have by-value or by-reference behavior when aN +is non-null. + +The compromise I've settled on is this: + +1. The default behavior is pass-by-value. If you pass a non-null + pointer, the pointee is copied into a new Python object; otherwise + the corresponding Python argument will be None. + +2. if you want by-reference behavior, use ptr(aN) if aN is a pointer + and ref(aN) otherwise. If a null pointer is passed to ptr(aN), the + corresponding Python argument will be None. + +RESULT HANDLING + +As for results, we have a similar problem: if ResultType is allowed to +be a pointer or reference type, the lifetime of the object it refers to +is probably being managed by a Python object. When that Python object is +destroyed, our pointer dangles. The problem is particularly bad when the +ResultType is char const* - the corresponding Python String object is +typically uniquely-referenced, meaning that the pointer dangles as soon +as returning::call() returns. + +Boost.Python v1 deals with this issue by refusing to compile any uses of +callback::call(), but IMO this goes both too far and not +far enough. It goes too far because there are cases where the owning +String object survives beyond the call (just for instance when it's the +name of a Python class), and it goes not far enough because we might +just as well have the same problem with any returned pointer or +reference. + +I propose to address this in Boost.Python v2 by + + 1. lifting the compile-time restriction on const + char* callback returns + + 2. detecting the case when the reference count on the + result Python object is 1 and throwing an exception + inside of returning::call() when U is a pointer or + reference type. + +I think this is acceptably safe because users have to explicitly specify +a pointer/reference for U in returning, and they will be protected +against dangles at runtime, at least long enough to get out of the +returning::call() invocation. + +-Dave + +**It would be possible to make it fail at compile-time for non-class +types such as int and char, but I'm not sure it's a good idea to impose +this restriction yet. diff --git a/libs/python/doc/v2/class.html b/libs/python/doc/v2/class.html new file mode 100644 index 0000000000..edfc609704 --- /dev/null +++ b/libs/python/doc/v2/class.html @@ -0,0 +1,790 @@ + + + + + + + + + + + + Boost.Python - <boost/python/class.hpp>, + <boost/python/class_fwd.hpp> + + + + + + + + + +
+

+

+
+

Boost.Python

+ +

Headers <boost/python/class.hpp>, + <boost/python/class_fwd.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class template + class_
+ +
+
+
Class class_ + synopsis
+ +
Class class_ + constructors
+ +
Class class_ + modifier functions
+
+
+ +
Class template bases
+ +
+
+
Class template + bases synopsis
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

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

+ +

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

+ +

Classes

+ +

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

+ +

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

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Template ParameterRequirementsSemanticsDefault
TA class type.The class being wrapped
BasesA specialization of bases<...> which + specifies previously-exposed C++ base classes of T[1].Registers from_python conversions from wrapped + T instances to each of its exposed direct and indirect + bases. For each polymorphic base B, registers conversions + from indirectly-held wrapped B instances to + T.bases<>
HeldTypeMust be T, a class derived from T, or a + Dereferenceable type for which + pointee<HeldType>::type is + T or a class derived from T.Specifies the type that is actually embedded in a Python object + wrapping a T instance when T's constructor is + called or when a T or T* is converted to + Python without the use of + ptr, + ref, or Call Policies + such as return_internal_reference. + More details below.T
NonCopyableIf supplied, must be boost::noncopyable.Suppresses automatic registration of to_python + conversions which copy T instances. Required when + T has no publicly-accessible copy constructor.An unspecified type other than + boost::noncopyable.
+ +

HeldType Semantics

+ +
    +
  1. If HeldType is derived from T, its exposed + constructor(s) must accept an initial PyObject* argument + which refers back to the Python object that contains the + HeldType instance, as shown in this example. This argument is not + included in the init-expression passed to def(init_expr), below, nor is + it passed explicitly by users when Python instances of T are + created. This idiom allows C++ virtual functions which will be overridden + in Python to access the Python object so the Python method can be + invoked. Boost.Python automatically registers additional converters which + allow wrapped instances of T to be passed to wrapped C++ + functions expecting HeldType arguments.
  2. + +
  3. Because Boost.Python will always allow wrapped instances of + T to be passed in place of HeldType arguments, + specifying a smart pointer for HeldType allows users to pass + Python T instances where a smart pointer-to-T + is expected. Smart pointers such as std::auto_ptr<> or + boost::shared_ptr<> + which contain a nested type element_type designating the + referent type are automatically supported; additional smart pointer types + can be supported by specializing pointee<HeldType>.
  4. + +
  5. As in case 1 above, when HeldType is a smart pointer to + a class derived from T, the initial PyObject* + argument must be supplied by all of HeldType's exposed + constructors.
  6. + +
  7. Except in cases 1 and 3, users may optionally specify that T itself + gets initialized with a similar initial PyObject* argument + by specializing has_back_reference<T>.
  8. +
+ +

Class + template class_ synopsis

+
+namespace boost { namespace python
+{
+  template <class T
+      , class Bases = bases<>
+            , class HeldType = T
+            , class NonCopyable = unspecified
+           >
+  class class_ : public object
+  {
+    // Constructors with default __init__
+    class_(char const* name);
+    class_(char const* name, char const* docstring);
+
+    // Constructors, specifying non-default __init__
+    template <class Init>
+    class_(char const* name, Init);
+    template <class Init>
+    class_(char const* name, char const* docstring, Init);
+
+    // Exposing additional __init__ functions
+    template <class Init>
+    class_& def(Init);
+
+    // defining methods
+    template <class F>
+    class_& def(char const* name, F f);
+    template <class Fn, class A1>
+    class_& def(char const* name, Fn fn, A1 const&);
+    template <class Fn, class A1, class A2>
+    class_& def(char const* name, Fn fn, A1 const&, A2 const&);
+    template <class Fn, class A1, class A2, class A3>
+    class_& def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
+
+    // declaring method as static
+    class_& staticmethod(char const* name);
+    
+    // exposing operators
+    template <unspecified>
+    class_& def(detail::operator_<unspecified>);
+
+    // Raw attribute modification
+    template <class U>
+    class_& setattr(char const* name, U const&);
+
+    // exposing data members
+    template <class D>
+    class_& def_readonly(char const* name, D T::*pm);
+
+    template <class D>
+    class_& def_readwrite(char const* name, D T::*pm);
+
+    // exposing static data members
+    template <class D>
+    class_& def_readonly(char const* name, D const& d);
+    template <class D>
+    class_& def_readwrite(char const* name, D& d);
+
+    // property creation
+    template <class Get>
+    void add_property(char const* name, Get const& fget, char const* doc=0);
+    template <class Get, class Set>
+    void add_property(
+        char const* name, Get const& fget, Set const& fset, char const* doc=0);
+
+    template <class Get>
+    void add_static_property(char const* name, Get const& fget);
+    template <class Get, class Set>
+    void add_static_property(char const* name, Get const& fget, Set const& fset);
+
+    // pickle support
+    template <typename PickleSuite>
+    self& def_pickle(PickleSuite const&);
+    self& enable_pickling();
+  };
+}}
+
+ +

Class template + class_ constructors

+
+class_(char const* name);
+class_(char const* name, char const* docstring);
+template <class Init>
+class_(char const* name, Init init_spec);
+template <class Init>
+class_(char const* name, char const* docstring, Init init_spec);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules. If docstring is supplied, it must be an + ntbs. If init_spec is + supplied, it must be either the special enumeration constant + no_init or an init-expression compatible with + T.
+ +
Effects: Constructs a class_ object holding a + Boost.Python extension class named name. The + named attribute of the current scope is bound to the new extension + class.
+ +
+
    +
  • If supplied, the value of docstring is bound to the + __doc__ attribute of the extension class.
  • + +
  • If init_spec is no_init, a special + __init__ function is generated which always raises a + Python exception. Otherwise, this->def(init_spec) is + called.
  • + +
  • If init_spec is not supplied, + this->def(init<>()) is called.
  • +
+
+ +
Rationale:Allowing the user to specify constructor arguments + in the class_<> constructor helps her to avoid the + common run-time errors which result from invoking wrapped member + functions without having exposed an __init__ function which + creates the requisite T instance. Types which are not + default-constructible will cause a compile-time error unless + Init is supplied. The user must always supply + name as there is currently no portable method to derive the + text of the class name from its type.
+
+ +

Class + template class_ modifier functions

+
+template <class Init>
+class_& def(Init init_expr);
+
+ +
+
Requires: init_expr is the result of an init-expression compatible with + T.
+ +
Effects: For each valid + prefix P of Init, adds an + __init__(...) function overload to the + extension class accepting P as arguments. Each overload + generated constructs an object of HeldType according to the + semantics described above, using a copy of + init_expr's call policies. + If the longest valid prefix of + Init contains N types and init_expr + holds M keywords, an initial sequence of the keywords are used + for all but the first N - M arguments of each + overload.
+ +
Returns: *this
+ +
Rationale: Allows users to easily expose a class' constructor + to Python.
+

+
+template <class F>
+class_& def(char const* name, Fn fn);
+template <class Fn, class A1>
+class_& def(char const* name, Fn fn, A1 const& a1);
+template <class Fn, class A1, class A2>
+class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2);
+template <class Fn, class A1, class A2, class A3>
+class_& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules.
+ +
+
    +
  • If a1 is the result of an overload-dispatch-expression, + only the second form is allowed and fn must be a pointer to function + or pointer to member function whose + arity is the same as A1's maximum + arity. + +
    +
    Effects: For each prefix P of + Fn's sequence of argument types, beginning with the + one whose length is A1's minimum + arity, adds a + name(...) method overload to + the extension class. Each overload generated invokes + a1's call-expression with P, using a copy + of a1's call + policies. If the longest valid prefix of A1 + contains N types and a1 holds M + keywords, an initial sequence of the keywords are used for all + but the first N - M arguments of each + overload.
    +
    +
  • + +
  • Otherwise, a single method overload is built around fn, which + must not be null: + +
      +
    • If fn is a function pointer, its first argument must be of + the form U, U cv&, U + cv*, or U cv* const&, + where T* is convertible to U*, and + a1-a3, if supplied, may be selected in + any order from the table below.
    • + +
    • Otherwise, if fn is a member function pointer, its target + must be T or one of its public base classes, and + a1-a3, if supplied, may be selected in + any order from the table below.
    • + +
    • Otherwise, Fn must be [derived from] + object, and + a1-a2, if supplied, may be selcted in any order from + the first two rows of the table below. To be useful, + fn should be + callable.
    • +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Memnonic NameRequirements/Type propertiesEffects
    docstringAny ntbs.Value will be bound to the __doc__ attribute + of the resulting method overload. If an earlier overload + supplied a docstring, two newline characters and the new + docstring are appended to it.
    policiesA model of CallPoliciesA copy will be used as the call policies of the resulting + method overload.
    keywordsThe result of a keyword-expression + specifying no more arguments than the arity of fn.A copy will be used as the call policies of the resulting + method overload.
    +
  • +
+
+ +
Returns: *this
+
+
+class_& staticmethod(char const* name);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules, and corresponds to a method whose overloads have all + been defined.
+ +
Effects: Replaces the existing named attribute x with + the result of invoking staticmethod(x) + in Python. Specifies that the corresponding method is static and + therefore no object instance will be passed to it. This is equivalent to + the Python statement:
+ +
+
+setattr(self, name, staticmethod(getattr(self, name)))
+
+
+ +
Note: Attempting to invoke def(name,...) after + invoking staticmethod(name) will raise a RuntimeError.
+ +
Returns: *this
+

+
+template <unspecified>
+class_& def(detail::operator_<unspecified>);
+
+ +
+
Effects: Adds a Python special method as + described here.
+ +
Returns: *this
+
+
+template <class U>
+class_& setattr(char const* name, U const& u);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules.
+ +
Effects: Converts u to Python and adds it to the attribute + dictionary of the extension class:
+ +
+
+ PyObject_SetAttrString(this->ptr(), + name, object(u).ptr()); +
+
+ +
Returns: *this
+

+
+template <class Get>
+void add_property(char const* name, Get const& fget, char const* doc=0);
+template <class Get, class Set>
+void add_property(
+        char const* name, Get const& fget, Set const& fset, char const* doc=0);
+
+ +
+
Requires: name is an ntbs which conform to Python's identifier + naming rules.
+ +
Effects: Creates a new Python property + class instance, passing object(fget) (and + object(fset) in + the second form) with an (optional) docstring doc to its + constructor, then adds that property to the Python class object under + construction with the given attribute name.
+ +
Returns: *this
+ +
Rationale: Allows users to easily expose functions that can be + invoked from Python with attribute access syntax.
+

+
+template <class Get>
+void add_static_property(char const* name, Get const& fget);
+template <class Get, class Set>
+void add_static_property(char const* name, Get const& fget, Set const& fset);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules.
+ +
Effects: Creates a Boost.Python.StaticProperty object, passing + object(fget) + (and object(fset) in the second + form) to its constructor, then adds that property to the Python class + under construction with the given attribute name. + StaticProperty is a special subclass of Python's property + class which can be called without an initial self + argument.
+ +
Returns: *this
+ +
Rationale: Allows users to easily expose functions that can be + invoked from Python with static attribute access syntax.
+

+
+template <class D>
+class_& def_readonly(char const* name, D T::*pm, char const* doc=0);
+template <class D>
+class_& def_readonly(char const* name, D const& d);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules. doc is also an ntbs.
+ +
Effects:
+ +
+
+this->add_property(name, make_getter(pm), doc);
+
and +
+this->add_static_property(name, make_getter(d));
+
respectively.
+
+
+ +
Returns: *this
+ +
Rationale: Allows users to easily expose a class' data member + or free variable such that it can be inspected from Python with a natural + syntax.
+
+
+template <class D>
+class_& def_readwrite(char const* name, D T::*pm, char const* doc=0);
+template <class D>
+class_& def_readwrite(char const* name, D& d);
+
+ +
+
Effects:
+ +
+
+this->add_property(name, make_getter(pm), make_setter(pm), doc);
+
and +
+this->add_static_property(name, make_getter(d), make_setter(d));
+
respectively.
+
+
+ +
Returns: *this
+ +
Rationale: Allows users to easily expose a class' data or free + variable member such that it can be inspected and set from Python with a + natural syntax.
+
+
+template <typename PickleSuite>
+class_& def_pickle(PickleSuite const&);
+
+ +
+
Requires: PickleSuite must be publically derived from pickle_suite.
+ +
Effects: Defines a legal combination of the special attributes + and methods: __getinitargs__, __getstate__, + __setstate__, __getstate_manages_dict__, + __safe_for_unpickling__, __reduce__
+ +
Returns: *this
+ +
Rationale: Provides an easy to use + high-level interface for establishing complete pickle support for the + wrapped class. The user is protected by compile-time consistency + checks.
+

+
+class_& enable_pickling();
+
+ +
+
Effects: Defines the __reduce__ method and the + __safe_for_unpickling__ attribute.
+ +
Returns: *this
+ +
Rationale: Light-weight alternative to + def_pickle(). Enables implementation of pickle support from Python.
+

+ +

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

+ +

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

+ +

Class + template bases synopsis

+
+namespace boost { namespace python
+{
+  template <T1 = unspecified,...Tn = unspecified>
+  struct bases
+  {};
+}}
+
+ +

Example(s)

+ +

Given a C++ class declaration:

+
+class Foo : public Bar, public Baz
+{
+ public:
+   Foo(int x, char const* y);
+   Foo(double);
+
+   std::string const& name() { return m_name; }
+   void name(char const*);
+
+   double value; // public data
+ private:
+   ...
+};
+
A corresponding Boost.Python extension class can be created with: +
+using namespace boost::python;
+
+class_<Foo,bases<Bar,Baz> >("Foo",
+          "This is Foo's docstring."
+          "It describes our Foo extension class",
+
+          init<int,char const*>(args("x","y"), "__init__ docstring")
+          )
+   .def(init<double>())
+   .def("get_name", &Foo::get_name, return_internal_reference<>())
+   .def("set_name", &Foo::set_name)
+   .def_readwrite("value", &Foo::value)
+   ;
+
+
+ [1] By "previously-exposed" we + mean that the for each B in bases, an instance of + class_<B, ...> must have + already been constructed. +
+class_<Base>("Base");
+class_<Derived, bases<Base> >("Derived");
+
Revised + + 1 November, 2005 + +

© Copyright Dave + Abrahams 2002.

+ + diff --git a/libs/python/doc/v2/configuration.html b/libs/python/doc/v2/configuration.html new file mode 100644 index 0000000000..1be862ed62 --- /dev/null +++ b/libs/python/doc/v2/configuration.html @@ -0,0 +1,217 @@ + + + + + + + + + + + + Boost.Python - Configuration + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Configuration

+
+
+ +
+
Introduction
+ +
Application Defined Macros
+ +
Library Defined Implementation + Macros
+
+ +

Introduction

+ +

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.

+ +

Application Defined Macros

+ +

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.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MacroDefaultMeaning
BOOST_PYTHON_MAX_ARITY15The 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_BASES10The 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_MODULEnot definedIf defined, prevents your module initialization + function from being treated as an exported symbol on platforms which + support that distinction in-code
BOOST_PYTHON_ENABLE_CDECLnot definedIf defined, allows functions using the __cdecl + calling convention to be wrapped.
BOOST_PYTHON_ENABLE_STDCALLnot definedIf defined, allows functions using the __stdcall + calling convention to be wrapped.
BOOST_PYTHON_ENABLE_FASTCALLnot definedIf defined, allows functions using the __fastcall + calling convention to be wrapped.
+ +

Library Defined Implementation + Macros

+ +

These macros are defined by Boost.Python and are implementation + details of interest only to implementors and those porting to new + platforms.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MacroDefaultMeaning
BOOST_PYTHON_TYPE_ID_NAMEnot definedIf 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_SIGNATURESnot definedIf 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_SIGNATURESdefined if BOOST_PYTHON_NO_PY_SIGNATURES is undefinedThis macro is defined to enable a smooth transition from older Boost.Python versions + which do not support pythonic signatures. For example usage see + here. +
BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPEnot definedIf 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).
+
+ +

Revised + + 7 January, 2003 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/copy_const_reference.html b/libs/python/doc/v2/copy_const_reference.html new file mode 100644 index 0000000000..97c2a282ce --- /dev/null +++ b/libs/python/doc/v2/copy_const_reference.html @@ -0,0 +1,149 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/copy_const_reference.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/copy_const_reference.hpp>

+
+
+ +

Contents

+ +
+
Classes
+ +
+
+
Class + copy_const_reference
+ +
+
+
Class + copy_const_reference synopsis
+ +
Class + copy_const_reference metafunctions
+
+
+
+
+ +
Example
+
+
+ +

Classes

+ +

Class + copy_const_reference

+ +

copy_const_reference is a model of ResultConverterGenerator + which can be used to wrap C++ functions returning a reference-to-const + type such that the referenced value is copied into a new Python + object.

+ +

Class + copy_const_reference synopsis

+
+namespace boost { namespace python
+{
+    struct copy_const_reference
+    {
+        template <class T> struct apply;
+    };
+}}
+
+ +

Class + copy_const_reference metafunctions

+
+template <class T> struct apply
+
+ +
+
Requires: T is U const& for + some U.
+ +
Returns: typedef to_python_value<T> + type;
+
+ +

Example

+ +

C++ Module Definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/copy_const_reference.hpp>
+#include <boost/python/return_value_policy.hpp>
+
+// classes to wrap
+struct Bar { int x; }
+
+struct Foo {
+   Foo(int x) : { b.x = x; }
+   Bar const& get_bar() const { return b; }
+ private:
+   Bar b;
+};
+
+// Wrapper code
+using namespace boost::python;
+BOOST_PYTHON_MODULE(my_module)
+{
+    class_<Bar>("Bar");
+
+     class_<Foo>("Foo", init<int>())
+        .def("get_bar", &Foo::get_bar
+            , return_value_policy<copy_const_reference>())
+       ;
+}
+
+ +

Python Code

+
+>>> from my_module import *
+>>> f = Foo(3)         # create a Foo object
+>>> b = f.get_bar()    # make a copy of the internal Bar object
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/copy_non_const_reference.html b/libs/python/doc/v2/copy_non_const_reference.html new file mode 100644 index 0000000000..987efad83d --- /dev/null +++ b/libs/python/doc/v2/copy_non_const_reference.html @@ -0,0 +1,149 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/copy_non_const_reference.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/copy_non_const_reference.hpp>

+
+
+ +

Contents

+ +
+
Classes
+ +
+
+
Class + copy_non_const_reference
+ +
+
+
Class + copy_non_const_reference synopsis
+ +
Class + copy_non_const_reference metafunctions
+
+
+
+
+ +
Example
+
+
+ +

Classes

+ +

Class + copy_non_const_reference

+ +

copy_non_const_reference is a model of ResultConverterGenerator + which can be used to wrap C++ functions returning a + reference-to-non-const type such that the referenced value is copied into + a new Python object.

+ +

Class + copy_non_const_reference synopsis

+
+namespace boost { namespace python
+{
+    struct copy_non_const_reference
+    {
+        template <class T> struct apply;
+    };
+}}
+
+ +

Class + copy_non_const_reference metafunctions

+
+template <class T> struct apply
+
+ +
+
Requires: T is U& for some + non-const U.
+ +
Returns: typedef to_python_value<T> + type;
+
+ +

Example

+ +

C++ code:

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/copy_non_const_reference.hpp>
+#include <boost/python/return_value_policy.hpp>
+
+// classes to wrap
+struct Bar { int x; }
+
+struct Foo {
+   Foo(int x) : { b.x = x; }
+   Bar& get_bar() { return b; }
+ private:
+   Bar b;
+};
+
+// Wrapper code
+using namespace boost::python;
+BOOST_PYTHON_MODULE(my_module)
+{
+    class_<Bar>("Bar");
+
+     class_<Foo>("Foo", init<int>())
+        .def("get_bar", &Foo::get_bar
+            , return_value_policy<copy_non_const_reference>())
+       ;
+}
+
+ Python Code: +
+>>> from my_module import *
+>>> f = Foo(3)         # create a Foo object
+>>> b = f.get_bar()    # make a copy of the internal Bar object
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/data_members.html b/libs/python/doc/v2/data_members.html new file mode 100644 index 0000000000..36f818d3d9 --- /dev/null +++ b/libs/python/doc/v2/data_members.html @@ -0,0 +1,229 @@ + + + + + + + + + + + + Boost.Python - <boost/python/data_members.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/data_members.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
make_getter
+ +
make_setter
+
+
+ +
Example
+
+
+ +

Introduction

+ +

make_getter() and + make_setter() are the + functions used internally by class_<>::def_readonly and + class_<>::def_readwrite to produce + Python callable objects which wrap C++ data members.

+ +

Functions

+
+template <class C, class D>
+object make_getter(D C::*pm);
+
+template <class C, class D, class Policies>
+object make_getter(D C::*pm, Policies const& policies);
+
+ +
+
Requires: Policies is a model of CallPolicies.
+ +
Effects: Creates a Python callable object which accepts a + single argument that can be converted from_python to + C*, and returns the corresponding member D + member of the C object, converted to_python. + If policies is supplied, it will be applied to the + function as described here. Otherwise, + the library attempts to determine whether D is a + user-defined class type, and if so uses return_internal_reference<>
+ +
for Policies. Note that this test may inappropriately + choose return_internal_reference<> in some cases + when D is a smart pointer type. This is a known + defect.
+ +
Returns: An instance of object which holds the new Python + callable object.
+
+
+template <class D>
+object make_getter(D const& d);
+template <class D, class Policies>
+object make_getter(D const& d, Policies const& policies);
+
+template <class D>
+object make_getter(D const* p);
+template <class D, class Policies>
+object make_getter(D const* p, Policies const& policies);
+
+ +
+
Requires: Policies is a model of CallPolicies.
+ +
Effects: Creates a Python callable object which accepts no + arguments and returns d or *p, converted + to_python on demand. If policies is supplied, + it will be applied to the function as described here. Otherwise, the library attempts to + determine whether D is a user-defined class type, and if + so uses reference_existing_object
+ +
for Policies.
+ +
Returns: An instance of object which holds the new Python + callable object.
+
+
+template <class C, class D>
+object make_setter(D C::*pm);
+
+template <class C, class D, class Policies>
+object make_setter(D C::*pm, Policies const& policies);
+
+ +
+
Requires: Policies is a model of CallPolicies.
+ +
Effects: Creates a Python callable object which, when called + from Python, expects two arguments which can be converted + from_python to C* and + D const&, respectively, and sets the + corresponding D member of the C object. If + policies is supplied, it will be applied to the function + as described here.
+ +
Returns: An instance of object which holds the new Python + callable object.
+
+
+template <class D>
+object make_setter(D& d);
+template <class D, class Policies>
+object make_setter(D& d, Policies const& policies);
+
+template <class D>
+object make_setter(D* p);
+template <class D, class Policies>
+object make_setter(D* p, Policies const& policies);
+
+ +
+
Requires: Policies is a model of CallPolicies.
+ +
Effects: Creates a Python callable object which accepts one + argument, which is converted from Python to D const& + and written into d or *p, respectively. If + policies is supplied, it will be applied to the function + as described here.
+ +
Returns: An instance of object which holds the new Python + callable object.
+
+ +

Example

+ +

The code below uses make_getter and make_setter to expose a data + member as functions:

+
+#include <boost/python/data_members.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+
+struct X
+{
+    X(int x) : y(x) {}
+    int y;
+};
+
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE_INIT(data_members_example)
+{
+    class_<X>("X", init<int>())
+       .def("get", make_getter(&X::y))
+       .def("set", make_setter(&X::y))
+       ;
+}
+
+ It can be used this way in Python: +
+>>> from data_members_example import *
+>>> x = X(1)
+>>> x.get()
+1
+>>> x.set(2)
+>>> x.get()
+2
+
+ +

+ + 5 August, 2003 +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/def.html b/libs/python/doc/v2/def.html new file mode 100644 index 0000000000..3c71fd363b --- /dev/null +++ b/libs/python/doc/v2/def.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + Boost.Python - <boost/python/def.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/def.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
def
+
+
+ +
Example
+
+
+ +

Introduction

+ +

def() is the function which can + be used to expose C++ functions and callable objects as Python functions + in the current scope.

+ +

Functions

+ def +
+template <class F>
+void def(char const* name, F f);
+
+template <class Fn, class A1>
+void def(char const* name, Fn fn, A1 const&);
+
+template <class Fn, class A1, class A2>
+void def(char const* name, Fn fn, A1 const&, A2 const&);
+
+template <class Fn, class A1, class A2, class A3>
+void def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules.
+ +
+
    +
  • If Fn is [derived from] object, it will be added to + the current scope as a single overload. To be useful, + fn should be callable.
  • + +
  • + If a1 is the result of an overload-dispatch-expression, + only the second form is allowed and fn must be a pointer to + function or pointer to member function whose arity is the same as A1's maximum + arity. + +
    +
    Effects: For each prefix P of + Fn's sequence of argument types, beginning with + the one whose length is A1's minimum + arity, adds a + name(...) function overload + to the current scope. Each overload + generated invokes a1's call-expression with + P, using a copy of a1's call policies. If the longest valid + prefix of A1 contains N types and + a1 holds M keywords, an initial sequence + of the keywords are used for all but the first + N - M arguments of each + overload.
    +
    +
    +
  • + +
  • Otherwise, fn must be a non-null function or member function + pointer, and a single function overload built around fn is added to + the current scope. If any of + a1-a3 are supplied, they may be selected + in any order from the table below.
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Memnonic NameRequirements/Type propertiesEffects
docstringAny ntbs.Value will be bound to the __doc__ attribute of + the resulting method overload.
policiesA model of CallPoliciesA copy will be used as the call policies of the resulting + method overload.
keywordsThe result of a keyword-expression + specifying no more arguments than the arity of fn.A copy will be used as the call policies of the resulting + method overload.
+
+
+ +

Example

+
+#include <boost/python/def.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/args.hpp>
+
+using namespace boost::python;
+
+char const* foo(int x, int y) { return "foo"; }
+
+BOOST_PYTHON_MODULE(def_test)
+{
+    def("foo", foo, args("x", "y"), "foo's docstring");
+}
+
+ +

+ + 7 March, 2003 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/def_visitor.html b/libs/python/doc/v2/def_visitor.html new file mode 100644 index 0000000000..08fa0c5145 --- /dev/null +++ b/libs/python/doc/v2/def_visitor.html @@ -0,0 +1,137 @@ + + + + + + Boost.Python - <boost/python/def_visitor.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header <boost/python/def_visitor.hpp>

+
+
+ +

Contents

+ + +
+
Introduction +
Classes +
+
+
Class def_visitor +
Class def_visitor + synopsis
+
Class def_visitor + requirements
+
+
Example +
+
+ +

Introduction

+ + +

<boost/python/def_visitor.hpp> provides a generic visitation + interface through which the class_ def member + functionality can be extended non-intrusively to avoid cluttering the class_ + interface. It declares the def_visitor<T> class template, + which is parameterized on the derived type DerivedVisitor, which provides + the actual def functionality through its visit member functions. +

Classes

+ +

Class template def_visitor<DerivedVisitor>

+ + +

The class def_visitor is a base class paramaterized by its derived class. The + def_visitor class is a protocol class. Its derived class, DerivedVisitor, is + expected to have a member function visit. The def_visitor class is never instantiated + directly. Instead, an instance of its subclass, DerivedVisitor,  is passed + on as an argument to the class_ def member function. +

+Class def_visitor synopsis

+
namespace boost { namespace python {
+
+    template <class DerivedVisitor>
+    class def_visitor {};
+}
+

def_visitor requirements

+ + +

The client supplied class DerivedVisitor + template parameter is expected to: +

    +
  • be privately derived from def_visitor
  • +
  • grant friend access to class def_visitor_access
  • +
  • define either or both visit member functions listed in the table below:
  • +
+ + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeRequirementsEffects
visitor.visit(cls)voidcls is an instance of a class_  being wrapped + to Python. visitor is a def_visitor derived class.A call to cls.def(visitor) forwards to this member function.
visitor.visit(cls, name, options)voidcls is a class_ instance, name is a C string. visitor is a def_visitor + derived class. options is a context specific optional argument.A call to cls.def(name, visitor) or cls.def(name, visitor, options) forwards + to this member function.
+ +

Example

+ + +
class X {/*...*/};
+class my_def_visitor : boost::python::def_visitor<my_def_visitor> +{ + friend class def_visitor_access; + + template <class classT> + void visit(classT& c) const + { + c + .def("foo", &my_def_visitor::foo) + .def("bar", &my_def_visitor::bar) + ; + } + + static void foo(X& self); + static void bar(X& self); +}; + +BOOST_PYTHON_MODULE(my_ext) +{ + class_<X>("X") + .def(my_def_visitor()) + ; +} +
+

Revised + 27 August, 2003 +

+ + +

© Copyright Joel de Guzman 2003. 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) diff --git a/libs/python/doc/v2/default_call_policies.html b/libs/python/doc/v2/default_call_policies.html new file mode 100644 index 0000000000..30d0a50de7 --- /dev/null +++ b/libs/python/doc/v2/default_call_policies.html @@ -0,0 +1,173 @@ + + + + + + Boost.Python - + <boost/python/default_call_policies.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header + <boost/python/default_call_policies.hpp>

+
+


+ +

Contents

+ +
+
Classes + +
+
+
Class + default_call_policies + +
+
+
Class + default_call_policies synopsis + +
Class + default_call_policies static functions +
+ +
Class + default_result_converter + +
+
+
Class + default_result_converter synopsis + +
Class + default_result_converter metafunctions +
+
+ +
Example +
+
+ +

Classes

+ +

Class + default_call_policies

+ +

default_call_policies is a model of CallPolicies with no precall or + postcall behavior and a result_converter which + handles by-value returns. Wrapped C++ functions and member functions use + default_call_policies unless otherwise specified. You may find + it convenient to derive new models of CallPolicies from + default_call_policies. + +

Class + default_call_policies synopsis

+
+namespace boost { namespace python
+{
+    struct default_call_policies
+    {
+        static bool precall(PyObject*);
+        static PyObject* postcall(PyObject*, PyObject* result);
+        typedef default_result_converter result_converter;
+        template <class Sig> struct extract_return_type : mpl::front<Sig>{};
+    };
+}}
+
+ +

Class + default_call_policies static functions

+
+bool precall(PyObject*);
+
+ +
+
Returns: true + +
Throws: nothing +
+
+PyObject* postcall(PyObject*, PyObject* result);
+
+ +
+
Returns: result + +
Throws: nothing +
+ +

Class + default_result_converter

+ +

default_result_converter is a model of ResultConverterGenerator which can be + used to wrap C++ functions returning non-pointer types, char + const*, and PyObject*, by-value. + +

Class + default_result_converter synopsis

+
+namespace boost { namespace python
+{
+    struct default_result_converter
+    {
+        template <class T> struct apply;
+    };
+}}
+
+ +

Class + default_result_converter metafunctions

+
+template <class T> struct apply
+
+ +
+
Requires: T is not a reference type. If + T is a pointer type, T is const + char* or PyObject*. + +
Returns: typedef to_python_value<T + const&> type; +
+ +

Example

+ +

This example comes from the Boost.Python implementation itself. Because + the return_value_policy + class template does not implement precall or + postcall behavior, its default base class is + default_call_policies: +

+template <class Handler, class Base = default_call_policies>
+struct return_value_policy : Base
+{
+   typedef Handler result_converter;
+};
+
+ +

Revised + + 11 June, 2007 + + + +

© Copyright Dave + Abrahams 2002. 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)

+ diff --git a/libs/python/doc/v2/definitions.html b/libs/python/doc/v2/definitions.html new file mode 100644 index 0000000000..cfec181c7f --- /dev/null +++ b/libs/python/doc/v2/definitions.html @@ -0,0 +1,102 @@ + + + + + + + + + + + + Boost.Python - Definitions + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Definitions

+
+
+ +
+
arity: The number of arguments 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. +
+ +

+
+ + +
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/dict.html b/libs/python/doc/v2/dict.html new file mode 100644 index 0000000000..82ea136536 --- /dev/null +++ b/libs/python/doc/v2/dict.html @@ -0,0 +1,152 @@ + + + + + + + + + + + + Boost.Python - <boost/python/dict.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/dict.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class dict
+ +
+
+
Class dict + synopsis
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

Exposes a TypeWrapper for the Python + dict + type.

+ +

Classes

+ +

Class dict

+ +

Exposes the mapping + protocol of Python's built-in dict type. The semantics + of the constructors and member functions defined below can be fully + understood by reading the TypeWrapper concept + definition. Since dict is publicly derived from object, the public object + interface applies to dict instances as well.

+ +

Class dict + synopsis

+
+namespace boost { namespace python
+{
+   class dict : public object
+   {
+      dict();
+
+      template< class T >
+      dict(T const & data);
+
+      // modifiers
+      void clear();
+      dict copy();
+
+      template <class T1, class T2>
+      tuple popitem();
+
+      template <class T>
+      object setdefault(T const &k);
+
+      template <class T1, class T2>
+      object setdefault(T1 const & k, T2 const & d);
+
+      void update(object_cref E);
+ 
+      template< class T >
+      void update(T const & E);
+
+      // observers
+      list values() const;
+    
+      object get(object_cref k) const;
+
+      template<class T>
+      object get(T const & k) const;
+
+      object get(object_cref k, object_cref d) const;
+      object get(T1 const & k, T2 const & d) const;
+
+      bool has_key(object_cref k) const;
+
+      template< class T >
+      bool has_key(T const & k) const;
+
+      list items() const;
+      object iteritems() const;
+      object iterkeys() const;
+      object itervalues() const;
+      list keys() const;
+  };
+}}
+
+ +

Example

+
+using namespace boost::python;
+dict swap_object_dict(object target, dict d)
+{
+    dict result = extract<dict>(target.attr("__dict__"));
+    target.attr("__dict__") = d;
+    return result;
+}
+
+ +

Revised 30 September, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/docstring_options.html b/libs/python/doc/v2/docstring_options.html new file mode 100644 index 0000000000..a2a0cc6459 --- /dev/null +++ b/libs/python/doc/v2/docstring_options.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/docstring_options.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/docstring_options.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class + docstring_options
+ +
+
+
Class + docstring_options synopsis
+ +
Class + docstring_options constructors
+ +
Class + docstring_options destructors
+ +
Class + docstring_options modifiers
+
+
+
+
+ +
Examples
+
+
+ +

Introduction

+ +

Boost.Python supports user-defined docstrings with automatic + appending of C++ signatures. These features are enabled by + default. The class docstring_options is available to + selectively suppress the user-defined docstrings, signatures, or + both.

+ +

Classes

+ +

Class + docstring_options

+ +

Controls the appearance of docstrings of wrapped functions and + member functions for the life-time of the instance. The instances + are noncopyable to eliminate the possibility of surprising side + effects.

+ +

Class + docstring_options synopsis

+
+namespace boost { namespace python {
+
+    class docstring_options : boost::noncopyable
+    {
+      public:
+          docstring_options(bool show_all=true);
+
+          docstring_options(bool show_user_defined, bool show_signatures);
+
+          docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
+
+          ~docstring_options();
+
+          void
+          disable_user_defined();
+
+          void
+          enable_user_defined();
+
+          void
+          disable_signatures();
+
+          void
+          enable_signatures();
+
+          void
+          disable_py_signatures();
+
+          void
+          enable_py_signatures();
+
+          void
+          disable_cpp_signatures();
+
+          void
+          enable_cpp_signatures();
+
+          void
+          disable_all();
+
+          void
+          enable_all();
+    };
+
+}}
+
+ +

Class + docstring_options constructors

+
+docstring_options(bool show_all=true);
+
+ +
+
Effects: Constructs a docstring_options + object which controls the appearance of function and + member-function docstrings defined in the code that follows. If + show_all is true, both the + user-defined docstrings and the automatically generated Python and C++ + signatures are shown. If show_all is + false the __doc__ attributes are + None.
+
+
+docstring_options(bool show_user_defined, bool show_signatures);
+
+ +
+
Effects: Constructs a docstring_options + object which controls the appearance of function and + member-function docstrings defined in the code that follows. + Iff show_user_defined is true, the + user-defined docstrings are shown. Iff + show_signatures is true, Python and C++ + signatures are automatically added. If both + show_user_defined and show_signatures + are false, the __doc__ attributes are + None.
+
+
+docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
+
+ +
+
Effects: Constructs a docstring_options + object which controls the appearance of function and + member-function docstrings defined in the code that follows. + Iff show_user_defined is true, the + user-defined docstrings are shown. Iff + show_py_signatures is true, Python + signatures are automatically added. Iff + show_cpp_signatures is true, C++ + signatures are automatically added. If all parameters are + false, the __doc__ attributes are + None.
+
+ +

Class + docstring_options destructors

+
+~docstring_options();
+
+ +
+
Effects: Restores the previous state of the + docstring options. In particular, if + docstring_options instances are in nested C++ + scopes the settings effective in the enclosing scope are + restored. If the last docstring_options instance + goes out of scope the default "all on" settings are + restored.
+
+ +

Class + docstring_options modifier functions

+
+void disable_user_defined();
+void enable_user_defined();
+void disable_signatures();
+void enable_signatures();
+void disable_py_signatures();
+void enable_py_signatures();
+void disable_cpp_signatures();
+void enable_cpp_signatures();
+void disable_all();
+void enable_all();
+
+ +
+
These member functions dynamically change the appearance of + docstrings in the code that follows. The + *_user_defined() and *_signatures() + member functions are provided for fine-grained control. The + *_all() member functions are convenient shortcuts + to manipulate all settings simultaneously.
+
+ +

Examples

+ +

Docstring options defined at compile time

+
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/docstring_options.hpp>
+
+void foo() {}
+
+BOOST_PYTHON_MODULE(demo)
+{
+    using namespace boost::python;
+    docstring_options doc_options(DEMO_DOCSTRING_SHOW_ALL);
+    def("foo", foo, "foo doc");
+}
+
If compiled with -DDEMO_DOCSTRING_SHOW_ALL=true: +
+>>> import demo
+>>> print demo.foo.__doc__
+foo() -> None : foo doc
+C++ signature:
+    foo(void) -> void
+
If compiled with +-DDEMO_DOCSTRING_SHOW_ALL=false: +
+>>> import demo
+>>> print demo.foo.__doc__
+None
+
+ +

Selective suppressions

+
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/docstring_options.hpp>
+
+int foo1(int i) { return i; }
+int foo2(long l) { return static_cast<int>(l); }
+int foo3(float f) { return static_cast<int>(f); }
+int foo4(double d) { return static_cast<int>(d); }
+
+BOOST_PYTHON_MODULE(demo)
+{
+    using namespace boost::python;
+    docstring_options doc_options;
+    def("foo1", foo1, arg("i"), "foo1 doc");
+    doc_options.disable_user_defined();
+    def("foo2", foo2, arg("l"), "foo2 doc");
+    doc_options.disable_signatures();
+    def("foo3", foo3, arg("f"), "foo3 doc");
+    doc_options.enable_user_defined();
+    def("foo4", foo4, arg("d"), "foo4 doc");
+    doc_options.enable_py_signatures();
+    def("foo5", foo4, arg("d"), "foo5 doc");
+    doc_options.disable_py_signatures();
+    doc_options.enable_cpp_signatures();
+    def("foo6", foo4, arg("d"), "foo6 doc");
+}
+
Python code: +
+>>> import demo
+>>> print demo.foo1.__doc__
+foo1( (int)i) -> int : foo1 doc
+C++ signature:
+    foo1(int i) -> int
+>>> print demo.foo2.__doc__
+foo2( (int)l) -> int : 
+C++ signature:
+    foo2(long l) -> int
+>>> print demo.foo3.__doc__
+None
+>>> print demo.foo4.__doc__
+foo4 doc
+>>> print demo.foo5.__doc__
+foo5( (float)d) -> int : foo5 doc
+>>> print demo.foo6.__doc__
+foo6 doc
+C++ signature:
+    foo6(double d) -> int
+
+ +

Wrapping from multiple C++ scopes

+
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/docstring_options.hpp>
+
+int foo1(int i) { return i; }
+int foo2(long l) { return static_cast<int>(l); }
+
+int bar1(int i) { return i; }
+int bar2(long l) { return static_cast<int>(l); }
+
+namespace {
+
+    void wrap_foos()
+    {
+        using namespace boost::python;
+        // no docstring_options here
+        //   -> settings from outer C++ scope are in effect
+        def("foo1", foo1, arg("i"), "foo1 doc");
+        def("foo2", foo2, arg("l"), "foo2 doc");
+    }
+
+    void wrap_bars()
+    {
+        using namespace boost::python;
+        bool show_user_defined = true;
+        bool show_signatures = false;
+        docstring_options doc_options(show_user_defined, show_signatures);
+        def("bar1", bar1, arg("i"), "bar1 doc");
+        def("bar2", bar2, arg("l"), "bar2 doc");
+    }
+}
+
+BOOST_PYTHON_MODULE(demo)
+{
+    boost::python::docstring_options doc_options(false);
+    wrap_foos();
+    wrap_bars();
+}
+
Python code: +
+>>> import demo
+>>> print demo.foo1.__doc__
+None
+>>> print demo.foo2.__doc__
+None
+>>> print demo.bar1.__doc__
+bar1 doc
+>>> print demo.bar2.__doc__
+bar2 doc
+
+ +

See also: boost/libs/python/test/docstring.cpp + and docstring.py

+ +

Revised + + 16 January, 2006 +

+ +

© Copyright Ralf W. + Grosse-Kunstleve 2006.

+ + diff --git a/libs/python/doc/v2/enum.html b/libs/python/doc/v2/enum.html new file mode 100644 index 0000000000..c5ec2b9217 --- /dev/null +++ b/libs/python/doc/v2/enum.html @@ -0,0 +1,234 @@ + + + + + + + + + + + + Boost.Python - <boost/python/enum.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/enum.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class template + enum_
+ +
+
+
Class template enum_ + synopsis
+ +
Class template enum_ + constructors
+ +
Class template enum_ + modifier functions
+
+
+ +
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

<boost/python/enum.hpp> defines the + interface through which users expose their C++ enumeration types + to Python. It declares the + enum_ class template, which is parameterized on the + enumeration type being exposed.

+ + +

Classes

+ +

Class template + enum_<T>

+ +

Creates a Python class derived from Python's int + type which is associated with the C++ type passed as its first + parameter. + +

Class template enum_ + synopsis

+
+namespace boost { namespace python
+{
+  template <class T>
+  class enum_ : public object
+  {
+    enum_(char const* name, char const* doc = 0);
+    enum_<T>& value(char const* name, T);
+    enum_<T>& export_values();
+  };
+}}
+
+ +

Class template enum_ + constructors

+
+enum_(char const* name, char const* doc=0);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules. + +
Effects: Constructs an enum_ object + holding a Python extension type derived from int + which is named name. The + named attribute of the current scope is bound to the new + extension type.
+
+ +

Class template + enum_ modifier functions

+
+inline enum_<T>& value(char const* name, T x);
+
+ +
+
Requires: name is an ntbs which conforms to Python's identifier + naming rules. + +
Effects: adds an instance of the wrapped enumeration + type with value x to the type's dictionary as the + named attribute.
+ +
Returns: *this
+ +
+ +
+inline enum_<T>& export_values();
+
+ +
+ +
Effects: sets attributes in the current scope with the + same names and values as all enumeration values exposed so far + by calling value().
+ +
Returns: *this
+ +
+ +

Example(s)

+ +

C++ module definition +

+#include <boost/python/enum.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/module.hpp>
+
+using namespace boost::python;
+
+enum color { red = 1, green = 2, blue = 4 };
+
+color identity_(color x) { return x; }
+
+BOOST_PYTHON_MODULE(enums)
+{
+    enum_<color>("color")
+        .value("red", red)
+        .value("green", green)
+        .export_values()
+        .value("blue", blue)
+        ;
+    
+    def("identity", identity_);
+}
+
+

Interactive Python: +

+>>> from enums import *
+
+>>> identity(red)
+enums.color.red
+
+>>> identity(color.red)
+enums.color.red
+
+>>> identity(green)
+enums.color.green
+
+>>> identity(color.green)
+enums.color.green
+
+>>> identity(blue)
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+NameError: name blue' is not defined
+
+>>> identity(color.blue)
+enums.color.blue
+
+>>> identity(color(1))
+enums.color.red
+
+>>> identity(color(2))
+enums.color.green
+
+>>> identity(color(3))
+enums.color(3)
+
+>>> identity(color(4))
+enums.color.blue
+
+>>> identity(1)
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+TypeError: bad argument type for built-in operation
+
+
+ + Revised + + 13 December, 2002 + + + +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/errors.html b/libs/python/doc/v2/errors.html new file mode 100644 index 0000000000..69a3cf5700 --- /dev/null +++ b/libs/python/doc/v2/errors.html @@ -0,0 +1,289 @@ + + + + + + + + + + + + Boost.Python - <boost/python/errors.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/errors.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class + error_already_set
+ +
+
+
Class + error_already_set synopsis
+
+
+
+
+ +
Functions
+ +
+
+
handle_exception
+ +
expect_non_null
+ +
throw_error_already_set
+
+
+ +
Examples
+
+
+ +

Introduction

+ +

<boost/python/errors.hpp> provides types and + functions for managing and translating between Python and C++ exceptions. + This is relatively low-level functionality that is mostly used internally + by Boost.Python. Users should seldom need it.

+ +

Classes

+ +

Class + error_already_set

+ +

error_already_set is an exception type which can be + thrown to indicate that a Python error has occurred. If thrown, the + precondition is that PyErr_Occurred() + returns a value convertible to true. Portable code shouldn't + throw this exception type directly, but should instead use throw_error_already_set(), + below.

+ +

Class error_already_set + synopsis

+
+namespace boost { namespace python
+{
+    class error_already_set {};
+}}
+
+ +

Functions

+
+template <class T> bool handle_exception(T f) throw();
+
+void handle_exception() throw();
+
+ +
+
Requires: The first form requires that the expression + function0<void>(f) + is valid. The second form requires that a C++ exception is currently + being handled (see section 15.1 in the C++ standard).
+ +
Effects: The first form calls f() inside a + try block which first attempts to use all registered exception translators. If none of + those translates the exception, the catch clauses then set + an appropriate Python exception for the C++ exception caught, returning + true if an exception was thrown, false + otherwise. The second form passes a function which rethrows the + exception currently being handled to the first form.
+ +
Postconditions: No exception is being handled
+ +
Throws: nothing
+ +
Rationale: At inter-language boundaries it is important to + ensure that no C++ exceptions escape, since the calling language + usually doesn't have the equipment necessary to properly unwind the + stack. Use handle_exception to manage exception + translation whenever your C++ code is called directly from the Python + API. This is done for you automatically by the usual function wrapping + facilities: make_function(), + make_constructor(), + def() and class_::def(). The second form can be + more convenient to use (see the example below), + but various compilers have problems when exceptions are rethrown from + within an enclosing try block.
+
+
+template <class T> T* expect_non_null(T* x);
+
+ +
+
Returns: x
+ +
Throws: error_already_set() iff x == + 0.
+ +
Rationale: Simplifies error-handling when calling functions + in the Python/C + API which return 0 on error.
+
+
+void throw_error_already_set();
+
+ +
+
Effects: throw error_already_set();
+
+ +
+
Rationale: Many platforms and compilers are not able to + consistently catch exceptions thrown across shared library boundaries. + Using this function from the Boost.Python library ensures that the + appropriate catch block in handle_exception() can catch the + exception.
+
+ +

Examples

+
+#include <string>
+#include <boost/python/errors.hpp>
+#include <boost/python/object.hpp>
+#include <boost/python/handle.hpp>
+
+// Returns a std::string which has the same value as obj's "__name__"
+// attribute.
+std::string get_name(boost::python::object obj)
+{
+   // throws if there's no __name__ attribute
+   PyObject* p = boost::python::expect_non_null(
+      PyObject_GetAttrString(obj.ptr(), "__name__"));
+
+   char const* s = PyString_AsString(p);
+   if (s != 0) 
+        Py_DECREF(p);
+
+   // throws if it's not a Python string
+   std::string result(
+      boost::python::expect_non_null(
+         PyString_AsString(p)));
+
+   Py_DECREF(p); // Done with p
+   
+   return result;
+}
+
+//
+// Demonstrate form 1 of handle_exception
+//
+
+// Place into result a Python Int object whose value is 1 if a and b have
+// identical "__name__" attributes, 0 otherwise.
+void same_name_impl(PyObject*& result, boost::python::object a, boost::python::object b)
+{
+   result = PyInt_FromLong(
+      get_name(a) == get_name(a2));
+}
+
+object borrowed_object(PyObject* p)
+{
+   return boost::python::object(
+        boost::python::handle<>(
+             boost::python::borrowed(a1)));
+}
+
+// This is an example Python 'C' API interface function
+extern "C" PyObject*
+same_name(PyObject* args, PyObject* keywords)
+{
+   PyObject* a1;
+   PyObject* a2;
+   PyObject* result = 0;
+
+   if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
+      return 0;
+   
+   // Use boost::bind to make an object compatible with
+   // boost::Function0<void>
+   if (boost::python::handle_exception(
+         boost::bind<void>(same_name_impl, boost::ref(result), borrowed_object(a1), borrowed_object(a2))))
+   {
+      // an exception was thrown; the Python error was set by
+      // handle_exception()
+      return 0;
+   }
+
+   return result;
+}
+
+//
+// Demonstrate form 2 of handle_exception. Not well-supported by all
+// compilers.
+//
+extern "C" PyObject*
+same_name2(PyObject* args, PyObject* keywords)
+{
+   PyObject* a1;
+   PyObject* a2;
+   PyObject* result = 0;
+
+   if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
+      return 0;
+
+   try {
+      return PyInt_FromLong(
+         get_name(borrowed_object(a1)) == get_name(borrowed_object(a2)));
+   }
+   catch(...)
+   {
+      // If an exception was thrown, translate it to Python
+      boost::python::handle_exception();
+      return 0;
+   }
+}
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/exception_translator.html b/libs/python/doc/v2/exception_translator.html new file mode 100644 index 0000000000..4cc7bb91b4 --- /dev/null +++ b/libs/python/doc/v2/exception_translator.html @@ -0,0 +1,150 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/exception_translator.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/exception_translator.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
register_exception_translator
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

As described here, it + is important to make sure that exceptions thrown by C++ code do not pass + into the Python interpreter core. By default, Boost.Python translates all + C++ exceptions thrown by wrapped functions and module init functions into + Python, but the default translators are extremely limited: most C++ + exceptions will appear in Python as a RuntimeError + exception whose representation is + 'Unidentifiable C++ Exception'. To produce better + error messages, users can register additional exception translators as + described below.

+ +

Functions

+ +

register_exception_translator

+ +
+template<class ExceptionType, class Translate>
+void register_exception_translator(Translate translate);
+
+ +
+
Requires:
+ +
+ Translate is Copyconstructible, and + the following code must be well-formed: +
+void f(ExceptionType x) { translate(x); }
+
+ The expression translate(x) must either throw a C++ + exception, or a subsequent call to PyErr_Occurred() + must return 1. +
+ +

+ +

Effects: Adds a copy of translate to the sequence of + exception translators tried when Boost.Python catches an exception that + is about to pass into Python's core interpreter. The new translator + will get "first shot" at translating all exceptions matching the catch + clause shown above. Any subsequently-registered translators will be + allowed to translate the exception earlier. A translator which cannot + translate a given C++ exception can re-throw it, and it will be handled + by a translator which was registered earlier (or by the default + translator).
+
+ +

Example

+
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/exception_translator.hpp>
+#include <exception>
+
+struct my_exception : std::exception
+{
+  char const* what() throw() { return "One of my exceptions"; }
+};
+
+void translate(my_exception const& e)
+{
+    // Use the Python 'C' API to set up an exception object
+    PyErr_SetString(PyExc_RuntimeError, e.what());
+}
+
+void something_which_throws()
+{
+    ...
+    throw my_exception();
+    ...
+}
+
+BOOST_PYTHON_MODULE(exception_translator_ext)
+{
+  using namespace boost::python;
+  register_exception_translator<my_exception>(&translate);
+  
+  def("something_which_throws", something_which_throws);
+}
+
+
+
+ +
+ +

Revised 03 October, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/exec.html b/libs/python/doc/v2/exec.html new file mode 100644 index 0000000000..83d2c9b896 --- /dev/null +++ b/libs/python/doc/v2/exec.html @@ -0,0 +1,163 @@ + + + + + + + + + + + Boost.Python - <boost/python/exec.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/exec.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
eval
+
exec
+
exec_file
+
+
+
Examples
+
+
+ +

Introduction

+ +

Exposes a mechanism for embedding the python interpreter into C++ code.

+ +

Functions

+ +

eval

+
+object eval(str expression,
+            object globals = object(),
+            object locals = object());
+    
+
+
Effects: + Evaluate Python expression from expression in the context + specified by the dictionaries globals and locals. +
+
Returns: + An instance of object + which holds the value of the expression. +
+
+ +

exec

+
+object exec(str code,
+            object globals = object(),
+            object locals = object());
+    
+
+
Effects: + Execute Python source code from code in the context + specified by the dictionaries globals and locals. +
+
Returns: + An instance of object + which holds the result of executing the code. +
+
+ +

exec_file

+
+object exec_file(str filename,
+                 object globals = object(),
+                 object locals = object());
+    
+
+
Effects: + Execute Python source code from the file named by filename + in the context specified by the dictionaries globals and + locals. +
+
Returns: + An instance of object + which holds the result of executing the code. +
+
+ +

Examples

+ + The following example demonstrates the use of import + and exec to define a function in python, and later call + it from within C++. + +
+#include <iostream>
+#include <string>
+
+using namespace boost::python;
+
+void greet()
+{ 
+  // Retrieve the main module.
+  object main = import("__main__");
+  
+  // Retrieve the main module's namespace
+  object global(main.attr("__dict__"));
+
+  // Define greet function in Python.
+  object result = exec(
+    "def greet():                   \n"
+    "   return 'Hello from Python!' \n",
+    global, global);
+
+  // Create a reference to it.
+  object greet = global["greet"];
+
+  // Call it.
+  std::string message = extract<std::string>(greet());
+  std::cout << message << std::endl;
+}
+
+ + Instead of embedding the python script into a string, + we could also store it in an a file... + +
+def greet():
+   return 'Hello from Python!'
+
+ ... and execute that instead. +
+  // ...
+  // Load the greet function from a file.
+  object result = exec_file(script, global, global);
+  // ...
+}
+
+

Revised 01 November, 2005

+ +

© Copyright Stefan Seefeld 2005.

+ + + diff --git a/libs/python/doc/v2/extract.html b/libs/python/doc/v2/extract.html new file mode 100644 index 0000000000..3c6b77f2f0 --- /dev/null +++ b/libs/python/doc/v2/extract.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + Boost.Python - <boost/python/extract.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/extract.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class extract
+ +
+
+
Class extract + synopsis
+ +
Class extract + constructors and destructor
+ +
Class + extract observer functions
+
+
+
+
+ + +
Example
+
+
+ +

Introduction

+ +

Exposes a mechanism for extracting C++ object values from + generalized Python objects. Note that + extract<...> can also be used to + "downcast" an object to some specific ObjectWrapper. Because + invoking a mutable python type with an argument of the same type + (e.g. list([1,2]) typically makes a copy of + the argument object, this may be the only way to access the ObjectWrapper's + interface on the original object. + +

Classes

+ +

Class template extract

+ +

extract<T> can be used to extract a value of + an arbitrary C++ type from an instance of object. Two usages are supported: +

    +
  1. extract<T>(o) is a temporary object +which is implicitly convertible to T (explicit conversion +is also available through the object's function-call +operator). However, if no conversion is available which can convert +o to an object of type T, a Python +TypeError exception will be raised. + +
  2. extract<T> x(o); constructs an extractor +whose check() member function can be used to ask whether +a conversion is available without causing an exception to be thrown. +
+ +

Class template extract + synopsis

+
+namespace boost { namespace python
+{
+  template <class T>
+  struct extract
+  {
+      typedef unspecified result_type;
+
+      extract(PyObject*);
+      extract(object const&);
+
+      result_type operator()() const;
+      operator result_type() const;
+
+      bool check() const;
+  };
+}}
+
+ +

Class extract + constructors and destructor

+
+extract(PyObject* p);
+extract(object const&);
+
+ +
+
Requires: The first form requires that p is non-null.
+ +
Effects:Stores a pointer to the Python object managed + by its constructor argument. In particular, the reference + count of the object is not incremented. The onus is on the user + to be sure it is not destroyed before the extractor's conversion + function is called.
+
+ +

Class extract + observer functions

+
+result_type operator()() const;
+operator result_type() const;
+
+ +
+
Effects: Converts the stored pointer to + result_type, which is either T or + T const&. +
+ +
Returns: An object of result_type + corresponding to the one referenced by the stored pointer.
+ +
Throws: error_already_set + and sets a TypeError if no such conversion is + available. May also emit other unspecified exceptions thrown by + the converter which is actually used.
+
+ +
+bool check() const;
+
+ +
+ +
Postconditions: None. In particular, note that a + return value of true does not preclude an exception + being thrown from operator result_type() or + operator()().
+ +
Returns: false only if no conversion from the + stored pointer to T is available.
+ +
+ + +

Examples

+ +
+#include <cstdio>
+using namespace boost::python;
+int Print(str s)
+{ 
+   // extract a C string from the Python string object
+   char const* c_str = extract<char const*>(s);
+
+   // Print it using printf
+   std::printf("%s\n", c_str);
+
+   // Get the Python string's length and convert it to an int
+   return extract<int>(s.attr("__len__")())
+}
+
+ +The following example shows how extract can be used along with +class_<...> +to create and access an instance of a wrapped C++ class. + +
+struct X
+{
+   X(int x) : v(x) {}
+   int value() { return v; }
+ private:
+   int v;
+};
+
+BOOST_PYTHON_MODULE(extract_ext)
+{
+    object x_class(
+       class_<X>("X", init<int>())
+          .def("value", &X::value))
+          ;
+        
+    // Instantiate an X object through the Python interface. 
+    // Its lifetime is now managed by x_obj.
+    object x_obj = x_class(3);
+
+    // Get a reference to the C++ object out of the Python object
+    X& x = extract<X&>(x_obj);
+    assert(x.value() == 3);
+}
+
+

Revised 15 November, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/faq.html b/libs/python/doc/v2/faq.html new file mode 100644 index 0000000000..75283d77ce --- /dev/null +++ b/libs/python/doc/v2/faq.html @@ -0,0 +1,861 @@ + + + + + + + + + + + + Boost.Python - FAQ + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Frequently Asked Questions (FAQs)

+
+
+ +
+ +
How can I wrap a function which takes a + function pointer as an argument?
+ +
I'm getting the "attempt to return dangling + reference" error. What am I doing wrong?
+ +
Is return_internal_reference + efficient?
+ +
How can I wrap functions which take C++ + containers as arguments?
+ +
fatal error C1204:Compiler limit:internal + structure overflow
+ +
How do I debug my Python extensions?
+ +
Why doesn't my *= operator + work?
+ +
Does Boost.Python work with Mac OS X?
+ +
How can I find the existing PyObject that holds a + C++ object?
+ +
How can I wrap a function which needs to take + ownership of a raw pointer?
+ +
Compilation takes too much time and eats too much memory! + What can I do to make it faster?
+ +
How do I create sub-packages using Boost.Python?
+ +
error C2064: term does not evaluate to a function taking 2 arguments +
+ +
How can I automatically convert my custom string type to + and from a Python string?
+ +
Why is my automatic to-python conversion not being + found?
+ +
Is Boost.Python thread-aware/compatible with multiple interpreters?
+
+
+ +

How can I wrap a function which takes a + function pointer as an argument?

+ + If what you're trying to do is something like this: +
+typedef boost::function<void (string s) > funcptr;
+
+void foo(funcptr fp)
+{
+    fp("hello,world!");
+}
+
+BOOST_PYTHON_MODULE(test)
+{
+    def("foo",foo) ;
+}
+
+ +And then: + +
+>>> def hello(s):
+...    print s
+...
+>>> foo(hello)
+hello, world!
+
+ + 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. + +

For more perspective on the issue, see this + posting. + +


+ +

I'm getting the "attempt to return dangling + reference" error. What am I doing wrong?

+ That exception is protecting you from causing a nasty crash. It usually + happens in response to some code like this: +
+period const& get_floating_frequency() const
+{
+  return boost::python::call_method<period const&>(
+      m_self,"get_floating_frequency");
+}
+
+ And you get: +
+ReferenceError: Attempt to return dangling reference to object of type:
+class period
+
+ +

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 class period) 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.
+  

+
+ +

Is return_internal_reference efficient?

+ +
+ 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 Version 2 + 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.

+
+
+ +

How can I wrap functions which take C++ + containers as arguments?

+ +

Ralf W. Grosse-Kunstleve provides these notes:

+ +
    +
  1. + Using the regular class_<> wrapper: +
    +class_<std::vector<double> >("std_vector_double")
    +  .def(...)
    +  ...
    +  ;
    +
    + 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).

    +
  2. + +
  3. + Using custom rvalue converters. Boost.Python "rvalue converters" + match function signatures such as: +
    +void foo(std::vector<double> const& array); // pass by const-reference
    +void foo(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. +
  4. +
+ 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:

+ +

C++:

+
+void foo(std::vector<double>& array)
+{
+  for(std::size_t i=0;i<array.size();i++) {
+    array[i] *= 2;
+  }
+}
+
+ Python: +
+>>> l = [1, 2, 3]
+>>> foo(l)
+>>> print l
+[2, 4, 6]
+
+ Custom lvalue converters require changes to the Boost.Python core library + and are currently not available. + +

P.S.:

+ +

The "scitbx" files referenced above are available via anonymous + CVS:

+
+cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx login
+cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
+
+
+ +

fatal error C1204:Compiler limit:internal + structure overflow

+ +
+ Q: I get this error message when compiling a large source + file. What can I do? + +

A: You have two choices:

+ +
    +
  1. Upgrade your compiler (preferred)
  2. + +
  3. + Break your source file up into multiple translation units. + +

    my_module.cpp:

    +
    +...
    +void more_of_my_module();
    +BOOST_PYTHON_MODULE(my_module)
    +{
    +   def("foo", foo);
    +   def("bar", bar);
    +   ...
    +   more_of_my_module();
    +}
    +
    + more_of_my_module.cpp: +
    +void more_of_my_module()
    +{
    +   def("baz", baz);
    +   ...
    +}
    +
    + 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: + +

    more_of_my_class.cpp:

    +
    +void more_of_my_class(class<my_class>& x)
    +{
    +   x
    +     .def("baz", baz)
    +     .add_property("xx", &my_class::get_xx, &my_class::set_xx)
    +     ;
    +
    +   ...
    +}
    +
    +
  4. +
+
+
+ +

How do I debug my Python extensions?

+ +

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.

+
+(gdb) target exec python
+(gdb) run
+ >>> from my_ext import *
+ >>> [C-c]
+(gdb) break MyClass::MyBuggyFunction
+(gdb) cont
+ >>> pyobj = MyClass()
+ >>> pyobj.MyBuggyFunction()
+Breakpoint 1, MyClass::MyBuggyFunction ...
+Current language:  auto; currently c++
+(gdb) do debugging stuff
+
+
+ +

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:

+ +

+

+$ gdb python
+GNU gdb 2003-09-02-cvs (cygwin-special)
+[...]
+
+(gdb) run
+Starting program: /cygdrive/c/Python22/python.exe
+Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
+Type "help", "copyright", "credits" or "license" for more information.
+>>> ^Z
+
+
+Program exited normally.
+(gdb) break *&PyOS_Readline
+Breakpoint 1 at 0x1e04eff0
+(gdb) run
+Starting program: /cygdrive/c/Python22/python.exe
+Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
+Type "help", "copyright", "credits" or "license" for more information.
+
+Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
+   from /cygdrive/c/WINNT/system32/python22.dll
+(gdb) cont
+Continuing.
+>>> from my_ext import *
+
+Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
+   from /cygdrive/c/WINNT/system32/python22.dll
+(gdb) # my_ext now loaded (with any debugging symbols it contains)
+
+
+ +

Debugging extensions through Boost.Build

+ 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: +
+bjam -sTOOLS=vc7.1 "--debugger=devenv /debugexe" test
+bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
+
+ 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. +
+ +

Why doesn't my *= operator work?

+ +
+ 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).

+
+>>> class X(object):
+...     def __imul__(self, x):
+...         print 'imul'
+...
+>>> x = X()
+>>> x *= 1
+
+ To cure this problem, all you need to do is upgrade your Python to + version 2.2.1 or later. +
+
+ +

Does Boost.Python work with Mac OS X?

+ + It is known to work under 10.2.8 and 10.3 using + Apple's gcc 3.3 compiler: +
gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1493)
+ Under 10.2.8 get the August 2003 gcc update (free at + http://connect.apple.com/). + Under 10.3 get the Xcode Tools v1.0 (also free). +

+ Python 2.3 is required. The Python that ships with 10.3 is + fine. Under 10.2.8 use these commands to install Python + as a framework: +

./configure --enable-framework
+make
+make frameworkinstall
+ 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.: +

limit stacksize 8192k
+ 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*
+   ') to type `void*' (source type is not polymorphic)
+ + 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:
struct your_type
+{
+  // before defining any member data
+#if defined(__MACH__) && defined(__APPLE_CC__) && __APPLE_CC__ == 1493
+  bool dummy_;
+#endif
+  // now your member data, e.g.
+  double x;
+  int j;
+  // etc.
+};
+ +
+

How can I find the existing PyObject that holds a C++ + object?

+ +
+ "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: +
+class X { X(int); virtual ~X(); ... };
+X* f();  // known to return Xs that are managed by Python objects
+
+
+// wrapping code
+
+struct X_wrap : X
+{
+    X_wrap(PyObject* self, int v) : self(self), X(v) {}
+    PyObject* self;
+};
+
+handle<> f_wrap()
+{
+    X_wrap* xw = dynamic_cast<X_wrap*>(f());
+    assert(xw != 0);
+    return handle<>(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.

+ +
+ +

How can I wrap a function which needs to take + ownership of a raw pointer?

+ +
+ Part of an API that I'm wrapping goes something like this: +
+struct A {}; struct B { void add( A* ); }
+where B::add() takes ownership of the pointer passed to it.
+
+ +

However:

+
+a = mod.A()
+b = mod.B()
+b.add( a )
+del a
+del b
+# python interpreter crashes
+# later due to memory corruption.
+
+ +

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: +
+void b_insert(B& b, std::auto_ptr<A> a)
+{
+    b.insert(a.get());
+    a.release();
+}
+
+ 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. + +
+

Compilation takes too much time and eats too + much memory! What can I do to make it faster?

+

+ Please refer to the Reducing Compiling Time section in the tutorial. +

+ +
+

How do I create sub-packages using Boost.Python?

+

+ Please refer to the Creating Packages section in the tutorial. +

+ +
+

error C2064: term does + not evaluate to a function taking 2 arguments

+ Niall Douglas provides these notes:

+ 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: +

boost\boost\python\detail\invoke.hpp(76):
+error C2064: term does not evaluate to a function taking 2 arguments"
+ This message is triggered by code like the following: +
#include <boost/python.hpp>
+
+using namespace boost::python;
+
+class FXThread
+{
+public:
+    bool setAutoDelete(bool doso) throw();
+};
+
+void Export_FXThread()
+{
+    class_< FXThread >("FXThread")
+        .def("setAutoDelete", &FXThread::setAutoDelete)
+    ;
+}
+    
+ The bug is related to the throw() modifier. + As a workaround cast off the modifier. E.g.: +
+        .def("setAutoDelete", (bool (FXThread::*)(bool)) &FXThread::setAutoDelete)
+

(The bug has been reported to Microsoft.)

+ +
+

How can I automatically + convert my custom string type to and from a Python string?

+ Ralf W. Grosse-Kunstleve provides these + notes:

+ Below is a small, self-contained demo extension module that shows + how to do this. Here is the corresponding trivial test: +

import custom_string
+assert custom_string.hello() == "Hello world."
+assert custom_string.size("california") == 10
+ + If you look at the code you will find: + +
    +
  • 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. + +
#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/to_python_converter.hpp>
+
+namespace sandbox { namespace {
+
+  class custom_string
+  {
+    public:
+      custom_string() {}
+      custom_string(std::string const& value) : value_(value) {}
+      std::string const& value() const { return value_; }
+    private:
+      std::string value_;
+  };
+
+  struct custom_string_to_python_str
+  {
+    static PyObject* convert(custom_string const& s)
+    {
+      return boost::python::incref(boost::python::object(s.value()).ptr());
+    }
+  };
+
+  struct custom_string_from_python_str
+  {
+    custom_string_from_python_str()
+    {
+      boost::python::converter::registry::push_back(
+        &convertible,
+        &construct,
+        boost::python::type_id<custom_string>());
+    }
+
+    static void* convertible(PyObject* obj_ptr)
+    {
+      if (!PyString_Check(obj_ptr)) return 0;
+      return obj_ptr;
+    }
+
+    static void construct(
+      PyObject* obj_ptr,
+      boost::python::converter::rvalue_from_python_stage1_data* data)
+    {
+      const char* value = PyString_AsString(obj_ptr);
+      if (value == 0) boost::python::throw_error_already_set();
+      void* storage = (
+        (boost::python::converter::rvalue_from_python_storage<custom_string>*)
+          data)->storage.bytes;
+      new (storage) custom_string(value);
+      data->convertible = storage;
+    }
+  };
+
+  custom_string hello() { return custom_string("Hello world."); }
+
+  std::size_t size(custom_string const& s) { return s.value().size(); }
+
+  void init_module()
+  {
+    using namespace boost::python;
+
+    boost::python::to_python_converter<
+      custom_string,
+      custom_string_to_python_str>();
+
+    custom_string_from_python_str();
+
+    def("hello", hello);
+    def("size", size);
+  }
+
+}} // namespace sandbox::<anonymous>
+
+BOOST_PYTHON_MODULE(custom_string)
+{
+  sandbox::init_module();
+}
+ +
+

Why is my automatic to-python conversion not being found?

+ Niall Douglas provides these notes:

+ 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: + +

.add_property("bar", make_getter(&foo::bar, return_internal_reference()))
+ + Similarly, def_readwrite("bar", &foo::bar) is + equivalent to: + +
.add_property("bar", make_getter(&foo::bar, return_internal_reference()),
+                     make_setter(&foo::bar, return_internal_reference())
+ + In order to define return value policies compatible with the + custom conversions replace def_readonly() and + def_readwrite() by add_property(). E.g.: + +
.add_property("bar", make_getter(&foo::bar, return_value_policy<return_by_value>()),
+                     make_setter(&foo::bar, return_value_policy<return_by_value>()))
+ +
+

Is Boost.Python thread-aware/compatible with multiple interpreters?

+ Niall Douglas provides these notes:

+ The quick answer to this is: no.

+

+ 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.

+ +
+ +

Revised + + 12 March, 2006 + +

+ +

© Copyright Dave Abrahams 2002-2006.

+ + diff --git a/libs/python/doc/v2/feb2002.html b/libs/python/doc/v2/feb2002.html new file mode 100644 index 0000000000..5f15aeace2 --- /dev/null +++ b/libs/python/doc/v2/feb2002.html @@ -0,0 +1,367 @@ + + + + + Boost.Python - February 2002 Progress Report + + + + +
+

+

+ +
+

Boost.Python

+ +

February 2002 Progress Report

+
+
+ +

Contents

+ +
+
Python10 Conference Report + +
Boost.Python v2 Progress + +
+
+
Documentation + +
Overhaul of + to_python/from_python + conversion mechanism + +
Miscellaneous +
+
+ +

Python10 Conference Report

+ I spent the first week of February at the Python10 conference + in Alexandria, VA. I'm including this experience report + for two reasons: firstly, it documents where my time was + used. Secondly, a public presence for Boost.Python and + interaction between the Python and C++ communities is + important to the future of Boost.Python, which in turn is + important to the Kull Project. + +

Andy Koenig, of all people, was the keynote speaker of + this year's opening plenary session. He presented his + "impressions of a polyglot outsider", which + studiously avoided any mention of C++ until the end of his + talk, when he was asked about standardization. I was + surprised to learn that the C++ community at large wanted a + few more years before beginning but when ANSI accepted + HP's request for a standard, the process was forced to + start: it was a matter of participating or having + standardization proceed without one's input. Andy managed + to highlight very effectively the balance of strengths in + Python, one of the most important being its support for + extension via libraries. In many ways that makes Python a + good analogue for C++ in the interpreted world + +

There were several kind mentions of the Boost.Python + library from people who found it indispensable. I was + particularly happy that Karl MacMillan, Michael Droettboom, + and Ichiro Fujinaga from Johns Hopkins is using it to do OCR + on a vast library of music notation, since in a previous life + I was an author of music notation software. These guys are + also drawing on Ullrich Koethe's VIGRA library for image + manipulation (Ullrich has been a major contributor to + Boost.Python). They also have a system for writing the + Boost.Python wrapper code in C++ comments, which allows them + to keep all of the code in one place. I've asked them to + send me some information on that. + +

The development of Swig has been gaining momentum again + (the basic description at + www.boost.org/libs/python/doc/comparisons.html still + applies). The talk given about it by David Beazly was very + well-attended, and they appear to have quite a few users. + Swig's strengths (coverage of many langauages) and + weaknesses (incomplete C++ language support) haven't + changed, although the C++ support seems to have improved + considerably - they now claim to have a complete model of the + C++ type system. It seems to be mostly geared at wrapping + what Walter Landry calls "C-Tran": C++ code which + traffics in built-in types with little use of abstraction. + I'm not knocking that, either: I'm sure a lot of that + code exists, so it's a valuable service. One feature Swig + has which I'd like to steal is the ability to unwrap a + single Python argument into multiple C++ arguments, for + example, by converting a Python string into a pointer and + length. When his talk was over, David approached me about a + possible joint workshop on language binding, which sounds + like a fun idea to me. + +

I spent some considerable time talking with Steven Knight, + the leader of the Scons build tool effort. We had a lot to + share with one another, and I gained a much better + appreciation for many of the Scons design decisions. Scons + seems to be concentrating on being the ultimate build system + substrate, and Steve seemed to think that we were on the + right track with our high-level design. We both hope that the + Boost.Build V2 high-level architecture can eventually be + ported to run on top of Scons. + +

They also have a highly-refined and successful development + procedure which I'd like to emulate for Boost.Build V2. + Among many other things they do, their source-control system + automatically ensures that when you check in a new test, it + is automatically run on the currently checked-in state of the + code, and is expected to fail -- a relatively obvious good + idea which I've never heard before. + +

Guido Van Rossum's "State of the Python + Union" address was full of questions for the community + about what should be done next, but the one idea Guido seemed + to stress was that core language stability and continuing + library development would be a good idea (sound familiar?) I + mentioned the Boost model as a counterpoint to the idea of + something like CPAN (the massive Perl library archives), and + it seemed to generate some significant interest. I've + offered to work with anyone from the Python community who + wants to set up something like Boost. + +

There was some discussion of "string + interpolation" (variable substitution in strings), and + Guido mentioned that he had some thoughts about the + strengths/weaknesses of Python's formatting interface. It + might be useful for those working on formatting for boost to + contact him and find out what he has to say. + +

Ka-Ping Yee demoed a Mailman discussion thread weaver. + This tool weaves the various messages in a discussion thread + into a single document so you can follow the entire + conversation. Since we're looking very seriously at + moving Boost to Mailman, this could be a really useful thing + for us to have. If we do this, we'll move the yahoogroups + discussions into the mailman archive so old discussions can + be easily accessed in the same fashion. + +

And, just because it's cool, though perhaps not + relevant: http://homepages.ulb.ac.be/~arigo/psyco/ is a + promising effort to accelerate the execution of Python code + to speeds approaching those of compiled languages. It + reminded me a lot of Todd Veldhuizen's research into + moving parts of C++ template compilation to runtime, only + coming from the opposite end of things. + +

Boost.Python v2 Progress

+ Here's what actually got accomplished. + +

Documentation

+ +

My first priority upon returning from Python10 was to get + some documentation in place. After wasting an unfortunate + amount of time looking at automatic documentation tools which + don't quite work, I settled down to use Bill Kempf's + HTML templates designed to be a boost standard. While they + are working well, it is highly labor-intensive. + +

I decided to begin with the high-level reference material, + as opposed to tutorial, narrative, or nitty-gritty details of + the framework. It seemed more important to have a precise + description of the way the commonly-used components work than + to have examples in HTML (since we already have some test + modules), and since the low-level details are much + less-frequently needed by users it made sense for me to + simply respond to support requests for the time being. + +

After completing approximately 60% of the high-level docs + (currently checked in to libs/python/doc/v2), I found myself + ready to start documenting the mechanisms for creating + to-/from-python converters. This caused a dilemma: I had + realized during the previous week that a much simpler, + more-efficient, and easier-to-use implementation was + possible, but I hadn't planned on implementing it right + away, since what was already in place worked adequately. I + had also received my first query on the C++-sig about how to + write such a converter + +

Given the labor-intensive nature of documentation writing, + I decided it would be a bad idea to document the conversion + mechanism if I was just going to rewrite it. Often the best + impetus for simplifying a design is the realization that + understandably documenting its current state would be too + difficult, and this was no exception. + +

Overhaul of + to_python/from_python conversion + mechanism

+ +

There were two basic realizations involved here: + +

    +
  1. to_python conversion could be a one-step + process, once an appropriate conversion function is found. + This allows elimination of the separate indirect + convertibility check + +
  2. There are basically two categories of from_python + conversions: those which lvalues stored within or held by + the Python object (essentially extractions), like what + happens when an instance of a C++ class exposed with class_ + is used as the target of a wrapped member function), and + those in which a new rvalue gets created, as when a Python + Float is converted to a C++ + complex<double> or a Python tuple is + converted to a C++ std::vector<>. From + the client side, there are two corresponding categories of + conversion: those which demand an lvalue conversion and + those which can accept an lvalue or an rvalue conversion. +
+ The latter realization allowed the following collapse, which + considerably simplified things: + +
+ + + + + + + + + + + + + + + + + +
Target Type + + Eligible Converters + +
T + + T rvalue or lvalue + +
T const + +
T volatile + +
T const volatile + +
T const& + +
T const* + + T lvalue + +
T volatile* + +
T const volatile* + +
T& + +
T volatile& + +
T const volatile& + +
T* const& + +
T const* const& + +
T volatile*const& + +
T const volatile*const& +
+
+ This job included the following additional enhancements: + +
    +
  • Elimination of virtual functions, which cause object + code bloat + +
  • Registration of a single converter function for all + lvalue conversions, two for all rvalue conversions + +
  • Killed lots of unneeded code + +
  • Increased opacity of registry interface + +
  • Eliminated all need for decorated runtime type + identifiers + +
  • Updated test modules to reflect new interface + +
  • Eliminated the need for users to worry about converter + lifetime issues Additional Builtin Conversion Enhancements + +
  • Support for complex<float>, + complex<double>, and complex<long double> + conversions + +
  • Support for bool conversions + +
  • NULL pointers representable by None in Python + +
  • Support for conversion of Python classic classes to + numeric types +
+ +

Miscellaneous

+ These don't fit easily under a large heading: + +
    +
  • Support CallPolicies for class member functions + +
  • from_python_data.hpp: revamped type alignment + metaprogram so that it's fast enough for KCC + +
  • classfwd.hpp header forward-declares class_<T> + +
  • indirect_traits.hpp: + +
  • added is_pointer_to_reference + +
  • fixed bugs + +
  • Reduced recompilation dependencies + +
  • msvc_typeinfo works around broken MS/Intel typeid() + implementation + +
  • Many fixes and improvements to the type_traits library + in order to work around compiler bugs and suppress warnings + +
  • Eliminated the need for explicit acquisition of + converter registrations + +
  • Expanded constructor support to 6 arguments + +
  • Implemented generalized pointer lifetime support + +
  • Updated code generation for returning.hpp + +
  • Tracked down and fixed cycle GC bugs + +
  • Added comprehensive unit tests for destroy_reference, + pointer_type_id, select_from_python, complex<T>, + bool, and classic class instance conversions +
+ +

Revised + + 13 November, 2002 + + + +

© Copyright Dave Abrahams 2002. 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)

+ diff --git a/libs/python/doc/v2/function_doc_signature.html b/libs/python/doc/v2/function_doc_signature.html new file mode 100644 index 0000000000..e439a77acb --- /dev/null +++ b/libs/python/doc/v2/function_doc_signature.html @@ -0,0 +1,216 @@ + + + + + + + + + + + Boost.Python - + <boost/python/doobject/function_doc_signature.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/object/function_doc_signature.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class + function_doc_signature_generator
+ +
+
+
Class + function_doc_signature_generator synopsis
+ +
+
+
+
+ +
Examples
+
+
+ +

Introduction

+ +

Boost.Python supports docstrings with automatic + appending of Pythonic and C++ signatures. This feature is implemented + by class function_doc_signature_generator + The class uses all of the overloads, supplied arg names and default values, as well as + the user-defined docstrings, to generate documentation for a given function.

+ +

Classes

+ +

Class + function_doc_signature_generator

+ +

+ The class has only one public function which returns a list of strings documenting the + overloads of a function. +

+ +

Class + function_doc_signature_generator synopsis

+
+namespace boost { namespace python { namespace objects {
+
+    class function_doc_signature_generator 
+    {
+      public:
+          static list function_doc_signatures(function const *f);
+    };
+
+}}}
+
+ + +

Examples

+ +

Docstrings generated with function_doc_signature_generator

+
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/tuple.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/overloads.hpp>
+#include <boost/python/raw_function.hpp>
+
+using namespace boost::python;
+
+tuple f(int x = 1, double y = 4.25, char const* z = "wow")
+{
+    return make_tuple(x, y, z);
+}
+
+BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
+
+
+struct X
+{
+    tuple f(int x = 1, double y = 4.25, char const* z = "wow")
+    {
+        return make_tuple(x, y, z);
+    }
+};
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 0, 3)
+
+tuple raw_func(tuple args, dict kw)
+{
+    return make_tuple(args, kw);
+}
+
+BOOST_PYTHON_MODULE(args_ext)
+{
+    def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow")
+        , "This is f's docstring"
+        );
+
+    def("raw", raw_function(raw_func));
+
+    def("f1", f, f_overloads("f1's docstring", args("x", "y", "z")));
+
+
+    class_<X>("X", "This is X's docstring", init<>(args("self")))
+        .def("f", &X::f
+             , "This is X.f's docstring"
+             , args("self","x", "y", "z"))
+
+        ;
+
+}
+
+
+Python code: +
+>>> import args_ext
+>>> help(args_ext)
+Help on module args_ext:
+
+NAME
+    args_ext
+
+FILE
+    args_ext.pyd
+
+CLASSES
+    Boost.Python.instance(__builtin__.object)
+        X
+
+    class X(Boost.Python.instance)
+     |  This is X's docstring
+     |
+     |  Method resolution order:
+     |      X
+     |      Boost.Python.instance
+     |      __builtin__.object
+     |
+     |  Methods defined here:
+     |
+     |  __init__(...)
+     |      __init__( (object)self) -> None :
+     |       C++ signature:
+     |           void __init__(struct _object *)
+     |
+     |  f(...)
+     |      f( (X)self, (int)x, (float)y, (str)z) -> tuple : This is X.f's docstring
+     |      C++ signature:
+     |          class boost::python::tuple f(struct X {lvalue},int,double,char const *)
+     |
+     |    .................
+     |
+FUNCTIONS
+    f(...)
+        f([ (int)x=1 [, (float)y=4.25 [, (str)z='wow']]]) -> tuple : This is f's docstring
+        C++ signature:
+            class boost::python::tuple f([ int=1 [,double=4.25 [,char const *='wow']]])
+
+    f1(...)
+        f1([ (int)x [, (float)y [, (str)z]]]) -> tuple : f1's docstring
+        C++ signature:
+            class boost::python::tuple f1([ int [,double [,char const *]]])
+
+    raw(...)
+        object raw(tuple args, dict kwds) :
+        C++ signature:
+            object raw(tuple args, dict kwds)
+
+
+
+ +

© Copyright Nikolay Mladenov 2007.

+ + diff --git a/libs/python/doc/v2/handle.html b/libs/python/doc/v2/handle.html new file mode 100644 index 0000000000..b20d94a1ff --- /dev/null +++ b/libs/python/doc/v2/handle.html @@ -0,0 +1,336 @@ + + + + + + + + + + + + Boost.Python - <boost/python/handle.hpp> + + + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/handle.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class template + handle
+ +
+
+
Class handle + synopsis
+ +
Class handle + constructors and destructor
+ +
Class handle + modifier functions
+ +
Class handle + observer functions
+
+
+
+
+ +
Functions
+ +
+
+
borrowed
+ +
allow_null
+
+
+
+
+ +

Introduction

+ +

<boost/python/handle.hpp> provides + class template handle, a smart pointer for + managing reference-counted Python objects.

+ +

Classes

+ +

Class template handle

+ +

handle is a smart pointer to a Python object type; it + holds a pointer of type T*, where T is its template + parameter. T must be either a type derived from + PyObject or a POD type + whose initial sizeof(PyObject) bytes are layout-compatible + with PyObject. Use handle<> at the + boundary between the Python/'C' API and high-level code; prefer object for a generalized + interface to Python objects.

+ +

In this document, the term "upcast" refers to an + operation which converts a pointer Y* to a base class + pointer T* via static_cast<T*> if + Y is derived from T, or via C-style cast + (T*) if it is not. However, in the latter case the "upcast" + is ill-formed if the initial sizeof(PyObject) bytes of + Y are not layout-compatible with PyObject.

+ +

Class template handle + synopsis

+
+namespace boost { namespace python
+{
+  template <class T>
+  class handle
+  {
+      typedef unspecified-member-function-pointer bool_type;
+
+   public: // types
+      typedef T element_type;
+
+   public: // member functions
+      ~handle();
+
+      template <class Y>
+      explicit handle(detail::borrowed<null_ok<Y> >* p);
+
+      template <class Y>
+      explicit handle(null_ok<detail::borrowed<Y> >* p);
+
+      template <class Y>
+      explicit handle(detail::borrowed<Y>* p);
+
+      template <class Y>
+      explicit handle(null_ok<Y>* p);
+
+      template <class Y>
+      explicit handle(Y* p);
+
+      handle();
+
+      handle& operator=(handle const& r);
+
+      template<typename Y>
+      handle& operator=(handle<Y> const & r); // never throws
+
+
+      template <typename Y>
+      handle(handle<Y> const& r);
+
+      handle(handle const& r);
+
+      T* operator-> () const;
+      T& operator* () const;
+      T* get() const;
+      void reset();
+      T* release();
+
+      operator bool_type() const; // never throws
+   private:
+      T* m_p;
+  };
+  
+  template <class T> struct null_ok;
+  namespace detail { template <class T> struct borrowed; }
+}}
+
+ +

Class handle constructors + and destructor

+
+virtual ~handle();
+
+ +
+
Effects: + Py_XDECREF(upcast<PyObject*>(m_p))
+
+
+template <class Y>
+explicit handle(detail::borrowed<null_ok<Y> >* p);
+
+ +
+
Effects: + Py_XINCREF(upcast<PyObject*>(p)); + m_p = upcast<T*>(p);
+
+
+template <class Y>
+explicit handle(null_ok<detail::borrowed<Y> >* p);
+
+ +
+
Effects: + Py_XINCREF(upcast<PyObject*>(p)); + m_p = upcast<T*>(p);
+
+
+template <class Y>
+explicit handle(detail::borrowed<Y>* p);
+
+ +
+
Effects: + Py_XINCREF(upcast<PyObject*>(p)); + m_p = upcast<T*>(expect_non_null(p));
+
+
+template <class Y>
+explicit handle(null_ok<Y>* p);
+
+ +
+
Effects: + m_p = upcast<T*>(p);
+
+
+template <class Y>
+explicit handle(Y* p);
+
+ +
+
Effects: + m_p = upcast<T*>(expect_non_null(p));
+
+
+handle();
+
+ +
+
Effects: m_p = 0;
+
+
+template <typename Y>
+handle(handle<Y> const& r);
+handle(handle const& r);
+
+ +
+
Effects: + m_p = r.m_p; Py_XINCREF(upcast<PyObject*>(m_p));
+
+ +

Class handle + modifiers

+
+handle& operator=(handle const& r);
+template<typename Y>
+handle& operator=(handle<Y> const & r); // never throws
+
+ +
+
Effects: + Py_XINCREF(upcast<PyObject*>(r.m_p)); Py_XDECREF( + upcast<PyObject*>(m_p)); m_p = r.m_p;
+
+
+T* release();
+
+ +
+
Effects: T* x = m_p; m_p = 0;return + x;
+
+
+void reset();
+
+ +
+
Effects: + *this = handle<T>();
+
+ +

Class handle + observers

+
+T* operator-> () const;
+T* get() const;
+
+ +
+
Returns: m_p;
+
+
+T& operator* () const;
+
+ +
+
Returns: *m_p;
+
+
+operator bool_type() const; // never throws
+
+ +
+
Returns: 0 if m_p == 0, a pointer + convertible to true otherwise.
+
+ +

Functions

+ +

borrowed

+
+template <class T>
+detail::borrowed<T>* borrowed(T* p)
+{
+    return (detail::borrowed<T>*)p;
+}
+
+ +

allow_null

+
+template <class T>
+null_ok<T>* allow_null(T* p)
+{
+    return (null_ok<T>*)p;
+}
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002 +.

+ + + diff --git a/libs/python/doc/v2/has_back_reference.html b/libs/python/doc/v2/has_back_reference.html new file mode 100644 index 0000000000..29b81506cd --- /dev/null +++ b/libs/python/doc/v2/has_back_reference.html @@ -0,0 +1,225 @@ + + + + + + + + + + + + Boost.Python - <boost/python/has_back_reference.hpp> + + + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/has_back_reference.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class template + has_back_reference
+ +
+
+
Class template + has_back_reference synopsis
+
+
+ +
Example(s)
+
+
+
+
+ +

Introduction

+ +

<boost/python/has_back_reference.hpp> defines the + predicate metafunction has_back_reference<>, which can + be specialized by the user to indicate that a wrapped class instance + holds a PyObject* corresponding to a Python object.

+ +

Classes

+ +

Class template + has_back_reference

+ +

A unary metafunction whose value is true iff its argument + is a pointer_wrapper<>.

+ +

Class template + has_back_reference synopsis

+
+namespace boost { namespace python
+{
+    template<class WrappedClass> class has_back_reference
+    { 
+        typedef mpl::false_ type;
+    };
+}}
+
+

A " + metafunction" that is inspected by Boost.Python to determine how + wrapped classes can be constructed.

+ +
+
type::value is an integral constant convertible to bool + of unspecified type.
+ +
Specializations may substitute a true-valued integral constant wrapper for + type iff for each invocation of + class_<WrappedClass>::def(init< + type-sequence...>()) and the implicitly wrapped + copy constructor (unless it is + noncopyable), there exists a corresponding constructor + WrappedClass::WrappedClass(PyObject*,  + type-sequence...). If such a specialization exists, + the WrappedClass constructors will be called with a "back + reference" pointer to the corresponding Python object whenever they are + invoked from Python. The easiest way to provide this nested +type + + is to + derive the specialization from mpl::true_. +
+
+ +

Example

+ +

C++ module definition

+
+#include <boost/python/class.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/has_back_reference.hpp>
+#include <boost/python/handle.hpp>
+#include <boost/shared_ptr.hpp>
+
+using namespace boost::python;
+using boost::shared_ptr;
+
+struct X
+{
+    X(PyObject* self) : m_self(self), m_x(0) {}
+    X(PyObject* self, int x) : m_self(self), m_x(x) {}
+    X(PyObject* self, X const& other) : m_self(self), m_x(other.m_x) {}
+    
+    handle<> self() { return handle<>(borrowed(m_self)); }
+    int get() { return m_x; }
+    void set(int x) { m_x = x; }
+
+    PyObject* m_self;
+    int m_x;
+};
+
+// specialize has_back_reference for X
+namespace boost { namespace python
+{
+  template <>
+  struct has_back_reference<X>
+    : mpl::true_
+  {};
+}}
+
+struct Y
+{
+    Y() : m_x(0) {}
+    Y(int x) : m_x(x) {}
+    int get() { return m_x; }
+    void set(int x) { m_x = x; }
+
+    int m_x;
+};
+
+shared_ptr<Y> 
+Y_self(shared_ptr<Y> self) { return self; }
+
+BOOST_PYTHON_MODULE(back_references)
+{
+    class_<X>("X")
+       .def(init<int>())
+       .def("self", &X::self)
+       .def("get", &X::get)
+       .def("set", &X::set)
+       ;
+
+    class_<Y, shared_ptr<Y> >("Y")
+       .def(init<int>())
+       .def("get", &Y::get)
+       .def("set", &Y::set)
+       .def("self", Y_self)
+       ;
+}
+
+ The following Python session illustrates that x.self() + returns the same Python object on which it is invoked, while + y.self() must create a new Python object which refers to the + same Y instance. + +

Python code

+
+>>> from back_references import *
+>>> x = X(1)
+>>> x2 = x.self()
+>>> x2 is x
+1
+>>> (x.get(), x2.get())
+(1, 1)
+>>> x.set(10)
+>>> (x.get(), x2.get())
+(10, 10)
+>>>
+>>>
+>>> y = Y(2)
+>>> y2 = y.self()
+>>> y2 is y
+0
+>>> (y.get(), y2.get())
+(2, 2)
+>>> y.set(20)
+>>> (y.get(), y2.get())
+(20, 20)
+
+ +

Revised + + 18 July, 2004 + +

+ +

© Copyright Dave Abrahams 2002 +.

+ + + diff --git a/libs/python/doc/v2/implicit.html b/libs/python/doc/v2/implicit.html new file mode 100644 index 0000000000..e9d5cac583 --- /dev/null +++ b/libs/python/doc/v2/implicit.html @@ -0,0 +1,163 @@ + + + + + + + + + + + + Boost.Python - <boost/python/implicit.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/implicit.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
Function Template + implicitly_convertible
+
+
+ +
Example
+
+
+ +

Introduction

+ implicitly_convertible allows Boost.Python to implicitly + take advantage of a C++ implicit or explicit conversion when matching + Python objects to C++ argument types. + +

Functions

+ +

Function template + implicitly_convertible

+
+template <class Source, class Target>
+void implicitly_convertible();
+
+ + + + + + + + + + + + + + + + + + + + + +
+ implicitly_convertible template parameters
+
ParameterDescription
SourceThe source type of the implicit conversion
TargetThe target type of the implicit conversion
+ +
+
Requires: The declaration Target t(s);, where + s is of type Source, is valid.
+ +
Effects: registers an rvalue from_python + converter to Target which can succeed for any + PyObject* p iff there exists any registered converter + which can produce Source rvalues
+ +
Rationale: C++ users expect to be able to take advantage of + the same sort of interoperability in Python as they do in C++.
+
+ +

Example

+ +

C++ module definition

+
+#include <boost/python/class.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/module.hpp>
+
+using namespace boost::python;
+
+struct X
+{
+    X(int x) : v(x) {}
+    operator int() const { return v; }
+    int v;
+};
+
+int x_value(X const& x)
+{
+    return x.v;
+}
+
+X make_x(int n) { return X(n); }
+
+BOOST_PYTHON_MODULE(implicit_ext)
+{
+    def("x_value", x_value);
+    def("make_x", make_x);
+
+    class_<X>("X", 
+        init<int>())
+        ;
+
+    implicitly_convertible<X,int>();
+    implicitly_convertible<int,X>();
+}
+
+ +

Python code

+
+>>> from implicit_ext import *
+>>> x_value(X(42))
+42
+>>> x_value(42)
+42
+>>> x = make_x(X(42))
+>>> x_value(x)
+42
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/import.html b/libs/python/doc/v2/import.html new file mode 100644 index 0000000000..15c1c68c55 --- /dev/null +++ b/libs/python/doc/v2/import.html @@ -0,0 +1,90 @@ + + + + + + + + + + + Boost.Python - <boost/python/import.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/import.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
import
+
+
+
Examples
+
+
+ +

Introduction

+ +

Exposes a mechanism for importing python modules.

+ +

Functions

+ +

import

+
+object import(str name);
+    
+
+
Effects: Imports the module named by name.
+
Returns: An instance of object + which holds a reference to the imported module.
+
+ +

Examples

+ + The following example demonstrates the use of import + to access a function in python, and later call it from within C++. + +
+#include <iostream>
+#include <string>
+
+using namespace boost::python;
+
+void print_python_version()
+{ 
+  // Load the sys module.
+  object sys = import("sys");
+
+  // Extract the python version.
+  std::string version = extract<std::string>(sys.attr("version"));
+  std::cout << version << std::endl;
+}
+
+

Revised 01 November, 2005

+ +

© Copyright Stefan Seefeld 2005.

+ + + diff --git a/libs/python/doc/v2/index.html b/libs/python/doc/v2/index.html new file mode 100644 index 0000000000..92593d06e7 --- /dev/null +++ b/libs/python/doc/v2/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + Loading index page; if nothing happens, please go to ../index.html. + + + diff --git a/libs/python/doc/v2/indexing.html b/libs/python/doc/v2/indexing.html new file mode 100644 index 0000000000..72c999c419 --- /dev/null +++ b/libs/python/doc/v2/indexing.html @@ -0,0 +1,695 @@ + + + + + + + + + + + Indexing Support + + + + + + + + +
+

+ C++ Boost +

+
+

+ Boost.Python +

+ +

Headers <boost/python/indexing/indexing_suite.hpp>
+ <boost/python/indexing/vector_indexing_suite.hpp>

+
+
+

+ Contents +

+
+
+ Introduction +
+
+ Interface +
+
+
+
+ indexing_suite +
+
+ indexing_suite + sub-classes +
+
+
+
+ vector_indexing_suite +
+
+
+
+
+
+
+
+ indexing_suite class +
+
+ vector_indexing_suite + class
+
map_indexing_suite class
+
+
+

+ Introduction +

+

+ Indexing is a Boost Python facility for easy exportation of indexable + C++ containers to Python. Indexable containers are containers that + allow random access through the operator[] (e.g. std::vector). +

+

+ While Boost Python has all the facilities needed to expose indexable + C++ containers such as the ubiquitous std::vector to Python, the + procedure is not as straightforward as we'd like it to be. Python + containers do not map easily to C++ containers. Emulating Python + containers in C++ (see Python Reference Manual, Emulating + container types) using Boost Python is non trivial. There are a lot + of issues to consider before we can map a C++ container to Python. + These involve implementing wrapper functions for the methods + __len__, __getitem__, + __setitem__, __delitem__, + __iter__ and __contains. +

+

+ The goals: +

+
    +
  • +
    + Make indexable C++ containers behave exactly as one would expect a + Python container to behave. +
    +
  • +
  • + Provide default reference semantics for container element indexing + (__getitem__) such that c[i] can be mutable. + Require: +
    +
    +    val = c[i]
    +    c[i].m()
    +    val == c[i]
    +          
    +
    where m is a non-const (mutating) member function + (method). +
  • +
  • + Return safe references from __getitem__ such that subsequent + adds and deletes to and from the container will not result in + dangling references (will not crash Python). +
  • +
  • + Support slice indexes. +
  • +
  • + Accept Python container arguments (e.g. lists, tuples) wherever + appropriate. +
  • +
  • + Allow for extensibility through re-definable policy classes. +
  • +
  • + Provide predefined support for the most common STL and STL like + indexable containers. +
  • +
+
+ +

The Boost.Python Indexing Interface

+

indexing_suite [ Header <boost/python/indexing/indexing_suite.hpp> + ]

+

+ The indexing_suite class is the base class for the + management of C++ containers intended to be integrated to Python. The + objective is make a C++ container look and feel and behave exactly as + we'd expect a Python container. The class automatically wraps these + special Python methods (taken from the Python reference: Emulating + container types): +

+
+
+
+
+ __len__(self) +
+
+ Called to implement the built-in function len()  Should return + the length of the object, an integer >= 0. Also, + an object that doesn't define a __nonzero__() method and whose __len__() method returns zero is considered to be + false in a Boolean context.   +
+
+
+
+ __getitem__(self, key) +
+
+ Called to implement evaluation of + self[key]. For sequence types, + the accepted keys should be integers and slice + objects.  Note that the special + interpretation of negative indexes (if the class wishes to + emulate a sequence type) is up to the __getitem__() method. If key is of + an inappropriate type, TypeError + may be raised; if of a value outside the set of indexes for + the sequence (after any special interpretation of negative + values), IndexError should be + raised. Note: + for loops expect that an IndexError will be raised for illegal + indexes to allow proper detection of the end of the + sequence. +
+
+
+
+ __setitem__(self, key, value) +
+
+ Called to implement assignment to + self[key]. Same note as for + __getitem__(). This should only be + implemented for mappings if the objects support changes to the + values for keys, or if new keys can be added, or for sequences if + elements can be replaced. The same exceptions should be raised + for improper key values as for the __getitem__() method. +
+
+
+
+ __delitem__(self, key) +
+
+ Called to implement deletion of + self[key]. Same note as for + __getitem__(). This should only be + implemented for mappings if the objects support removal of keys, + or for sequences if elements can be removed from the sequence. + The same exceptions should be raised for improper key + values as for the __getitem__() method. +
+
+
+
+ __iter__(self) +
+
+ This method is called when an iterator is required for a + container. This method should return a new iterator object that + can iterate over all the objects in the container. For mappings, + it should iterate over the keys of the container, and should also + be made available as the method iterkeys(). +

+ Iterator objects also need to implement this method; they are + required to return themselves. For more information on iterator + objects, see ``Iterator + Types'' in the Python Library Reference. +

+
+
+
+
+ __contains__(self, item) +
+
+ Called to implement membership test operators. Should return true + if item is in self, false otherwise. For + mapping objects, this should consider the keys of the mapping + rather than the values or the key-item pairs. +
+
+
+
+ +

indexing_suite sub-classes

+

+ The indexing_suite is not meant to be used as is. A couple of + policy functions must be supplied by subclasses of + indexing_suite. However, a set of indexing_suite + subclasses for the standard indexable STL containers will be provided, + In most cases, we can simply use the available predefined suites. In + some cases, we can refine the predefined suites to suit our needs. +

+ +

vector_indexing_suite [ Header <boost/python/indexing/vector_indexing_suite.hpp> + ]

+

+ The vector_indexing_suite class is a predefined + indexing_suite derived class designed to wrap + std::vector (and std::vector like [i.e. a class with + std::vector interface]) classes. It provides all the policies required by the + indexing_suite. +

+

+ Example usage: +

+
+    class X {...};
+    ...
+
+    class_<std::vector<X> >("XVec")
+        .def(vector_indexing_suite<std::vector<X> >())
+    ;
+
+

+ XVec is now a full-fledged Python container (see the + example in full, + along with its python + test). +

+

map_indexing_suite [ Header <boost/python/indexing/map_indexing_suite.hpp> ]

+

The map_indexing_suite class is a predefined indexing_suite derived class designed to wrap std::map (and std::map like [i.e. a class with std::map interface]) classes. It provides all the policies required by the indexing_suite.

+

Example usage:

+
+    class X {...};
+    ...
+
+    class_<std::map<X> >("XMap")
+        .def(map_indexing_suite<std::map<X> >())
+    ;
+
+

By default indexed elements are returned by proxy. This can be disabled by supplying true in the NoProxy template parameter. XMap is now a full-fledged Python container (see the example in full, along with its python test).

+
+

+ indexing_suite class

+

indexing_suite<
+
class Container
+ , class DerivedPolicies
+
, + bool NoProxy
+ , + bool NoSlice
+
, class Data
+ , class Index
+
, class Key

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Template Parameter
+
+ Requirements + + Semantics + + Default +
+ Container + + A class type + + The container type to be wrapped to Python. +   + +
+ DerivedPolicies + + A subclass of indexing_suite + + Derived classes provide the policy hooks. See DerivedPolicies below. +   + +
NoProxy A boolean By default indexed elements have Python reference semantics and are returned by proxy. This can be disabled by supplying true in the NoProxy template parameter. false
+ NoSlice + + A boolean + + Do not allow slicing. + false +
+ Data +   + + + The container's data type. + + Container::value_type +
Index   The container's index type. Container::size_type
+ Key +   + + + The container's key type. + + Container::value_type +
+
+    template <
class Container + , class DerivedPolicies + , bool NoProxy = false
, bool NoSlice = false + , class Data = typename Container::value_type + , class Index = typename Container::size_type + , class Key = typename Container::value_type + >
class indexing_suite + : unspecified + { + public: + + indexing_suite(); // default constructor + } +
+

+ DerivedPolicies +

+
+
+ Derived classes provide the hooks needed by + the indexing_suite: +
+
+
        data_type&
+        get_item(Container& container, index_type i);
+
+        static object
+        get_slice(Container& container, index_type from, index_type to);
+
+        static void
+        set_item(Container& container, index_type i, data_type const& v);
+
+        static void
+        set_slice(
+            Container& container, index_type from,
+            index_type to, data_type const& v
+        );
+
+        template <class Iter>
+        static void
set_slice(Container& container, index_type from, + index_type to, Iter first, Iter last + ); + + static void + delete_item(Container& container, index_type i); + + static void + delete_slice(Container& container, index_type from, index_type to); + + static size_t + size(Container& container); + + template <class T> + static bool + contains(Container& container, T const& val); + + static index_type + convert_index(Container& container, PyObject* i); + + static index_type + adjust_index(index_type current, index_type from, + index_type to, size_type len + ); +
+
+

+ Most of these policies are self explanatory. However, + convert_index and + adjust_index deserve some explanation. +

+

+ convert_index converts a Python index into + a C++ index that the container can handle. For instance, negative + indexes in Python, by convention, start counting from the right(e.g. + C[-1] indexes the rightmost element in C). + convert_index should handle the necessary + conversion for the C++ container (e.g. convert -1 to + C.size()-1). convert_index should + also be able to convert the type of the index (A dynamic Python type) + to the actual type that the C++ container expects. +

+

+ When a container expands or contracts, held indexes to its elements + must be adjusted to follow the movement of data. For instance, if we + erase 3 elements, starting from index 0 from a 5 element vector, what + used to be at index 4 will now be at index 1: +

+
+    [a][b][c][d][e] ---> [d][e]
+                 ^           ^
+                 4           1
+
+

+ adjust_index takes care of the adjustment. + Given a current index, the function should return the adjusted index + when data in the container at index from..to is + replaced by len elements. +

+
+
+
+

+ vector_indexing_suite class +

+

+ Class template
+ vector_indexing_suite<
+ class Container
+ , bool NoProxy
+ , class DerivedPolicies>
+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Template Parameter
+
+ Requirements + + Semantics + + Default +
+ Container + + A class type + + The container type to be wrapped to Python. +   + +
+ NoProxy + + A boolean + + By default indexed elements have Python reference semantics and + are returned by proxy. This can be disabled by supplying + true in the NoProxy template parameter. + + false +
+ DerivedPolicies + + A subclass of indexing_suite + + The vector_indexing_suite may still be derived to + further tweak any of the predefined policies. Static polymorphism + through CRTP (James Coplien. "Curiously Recurring Template + Pattern". C++ Report, Feb. 1995) enables the base + indexing_suite class to call policy function of the most + derived class +   + +
+
+    template <
class Container,
bool NoProxy = false,
class DerivedPolicies = unspecified_default
class vector_indexing_suite : unspecified_base
{
public:

typedef typename Container::value_type data_type;
typedef typename Container::value_type key_type;
typedef typename Container::size_type index_type;
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;

data_type&
get_item(Container& container, index_type i); + + static object + get_slice(Container& container, index_type from, index_type to); + + static void
set_item(Container& container, index_type i, data_type const& v); + + static void + set_slice(Container& container, index_type from, + index_type to, data_type const& v); + + template <class Iter>
static void
set_slice(Container& container, index_type from,
index_type to, Iter first, Iter last); + + static void + delete_item(Container& container, index_type i); + + static void + delete_slice(Container& container, index_type from, index_type to);
+ static size_t + size(Container& container); + + static bool + contains(Container& container, key_type const& key); + + static index_type + convert_index(Container& container, PyObject* i); + + static index_type + adjust_index(index_type current, index_type from, + index_type to, size_type len); + }; + +
+

map_indexing_suite class

+

Class template
+ map_indexing_suite<
+ class Container
+ , bool NoProxy
+ , class DerivedPolicies>

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Template Parameter
+
Requirements Semantics Default
Container A class type The container type to be wrapped to Python.  
NoProxy A boolean By default indexed elements have Python reference semantics and are returned by proxy. This can be disabled by supplying true in the NoProxy template parameter. false
DerivedPolicies A subclass of indexing_suite The vector_indexing_suite may still be derived to further tweak any of the predefined policies. Static polymorphism through CRTP (James Coplien. "Curiously Recurring Template Pattern". C++ Report, Feb. 1995) enables the base indexing_suite class to call policy function of the most derived class  
+
+    template <
class Container,
bool NoProxy = false,
class DerivedPolicies = unspecified_default
class map_indexing_suite : unspecified_base
{
public:

typedef typename Container::value_type value_type;
typedef typename Container::value_type::second_type data_type;
typedef typename Container::key_type key_type;
typedef typename Container::key_type index_type;
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;

static data_type&
get_item(Container& container, index_type i); + + static void
set_item(Container& container, index_type i, data_type const& v); + + static void + delete_item(Container& container, index_type i);
+ static size_t + size(Container& container); + + static bool + contains(Container& container, key_type const& key); + + static bool
compare_index(Container& container, index_type a, index_type b); +
static index_type + convert_index(Container& container, PyObject* i); + }; + +
+
+ © Copyright Joel de Guzman 2003. Permission to copy, use, modify, + sell and distribute this document is granted provided this copyright + notice appears in all copies. This document is provided "as is" without + express or implied warranty, and with no claim as to its suitability + for any purpose. +
+ + diff --git a/libs/python/doc/v2/init.html b/libs/python/doc/v2/init.html new file mode 100644 index 0000000000..2aacaad9f4 --- /dev/null +++ b/libs/python/doc/v2/init.html @@ -0,0 +1,251 @@ + + + + + + + + + + + + Boost.Python - <boost/python/init.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Headers <boost/python/init.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
init-expressions
+ +
Classes
+ +
+
+
Class template init
+ +
+
+
Class template + init synopsis
+ +
Class init + constructors
+ +
+
+ +
Class template + optional
+ +
+
+
Class template + optional synopsis
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

<boost/python/init.hpp> defines the interface for + exposing C++ constructors to Python as extension class + __init__ functions.

+ +

init-expressions

+ An init-expression is used to describe a family of + __init__ methods to be generated for an extension class, and + the result has the following properties: + +
+
+
docstring: An ntbs + whose value will bound to the method's __doc__ + attribute
+ +
keywords: A keyword-expression which will be + used to name (a trailing subsequence of) the arguments to the + generated __init__ function(s).
+ +
call policies: An instance of a model of CallPolicies.
+ +
argument types: An MPL sequence of C++ argument types + which will be used to construct the wrapped C++ object. An init + expression has one or more + valid prefixes which are given by a sequence of + prefixes of its argument types.
+
+
+ +

Classes

+ +

Class template init<T1 = + unspecified, T2 = + unspecified,...Tn = + unspecified>

+ +

A MPL sequence which + can be used to specify a family of one or more __init__ + functions. Only the last Ti supplied + may be an instantiation of optional<...>.

+ +

Class template init + synopsis

+
+namespace boost { namespace python
+{
+  template <T1 = unspecified,...Tn = unspecified>
+  struct init
+  {
+      init(char const* doc = 0);
+      template <class Keywords> init(Keywords const& kw, char const* doc = 0);
+      template <class Keywords> init(char const* doc, Keywords const& kw);
+
+      template <class CallPolicies>
+      unspecified operator[](CallPolicies const& policies) const
+  };
+}}
+
+ +

Class template init + constructors

+
+init(char const* doc = 0);
+template <class Keywords> init(Keywords const& kw, char const* doc = 0);
+template <class Keywords> init(char const* doc, Keywords const& kw);
+
+ +
+
Requires: If supplied, doc is an ntbs. If supplied, kw is the + result of a
+ +
Effects: The result is an init-expression whose + docstring is doc and whose keywords are + a reference to kw. If the first form is used, the + resulting expression's keywords are empty. The expression's + call policies are an instance of default_call_policies. + If Tn is optional<U1, U2,... + Um>, the + expression's valid prefixes are given by:
+ +
+
+ (T1, T2,...Tn-1), + (T1, T2,...Tn-1 + , U1), + (T1, T2,...Tn-1 + , U1, U2), + ...(T1, T2,...Tn-1 + , U1, U2,...Um). +
+ Otherwise, the expression has one valid prefix given by the + the template arguments the user specified. +
+
+ +

Class template init + observer functions

+
+template <class Policies>
+unspecified operator[](Policies const& policies) const
+
+ +
+
Requires: Policies is a model of CallPolicies.
+ +
Effects: Returns a new init-expression with all the same + properties as the init object except that its call + policies are replaced by a reference to + policies.
+
+ +

Class template optional<T1 + = unspecified, T2 = + unspecified,...Tn = + unspecified>

+ +

A MPL sequence which + can be used to specify the optional arguments to an __init__ + function.

+ +

Class template + optional synopsis

+
+namespace boost { namespace python
+{
+  template <T1 = unspecified,...Tn = unspecified>
+  struct optional {};
+}}
+
+ +

Example(s)

+ +

Given the C++ declarations:

+
+class Y;
+class X
+{
+ public:
+   X(int x, Y* y) : m_y(y) {}
+   X(double);
+ private:
+   Y* m_y;
+};
+
+ A corresponding Boost.Python extension class can be created with: +
+using namespace boost::python;
+
+class_<X>("X", "This is X's docstring.",
+          init<int,char const*>(args("x","y"), "X.__init__'s docstring")[
+                with_custodian_and_ward<1,3>()]
+          )
+   .def(init<double>())
+   ;
+
+
+ Revised + + 13 November, 2002 + + + +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/instance_holder.html b/libs/python/doc/v2/instance_holder.html new file mode 100644 index 0000000000..87571d1da8 --- /dev/null +++ b/libs/python/doc/v2/instance_holder.html @@ -0,0 +1,219 @@ + + + + + + + + + + + + + Boost.Python - <boost/python/instance_holder.hpp> + + + + + + + +
+

C++ Boost

+ +
+

Boost.Python

+ +

Header <boost/python/instance_holder.hpp>

+
+
+ +

Contents

+ +
+
Introduction + +
Classes + +
+
+
Class + instance_holder + +
+
+
Class + instance_holder synopsis + +
Class + instance_holder destructor + +
Class + instance_holder modifier functions + +
Class + instance_holder observer functions +
+
+ +
Example +
+
+ +

Introduction

+ +

<boost/python/instance_holder.hpp> provides + class instance_holder, the base class for types + which hold C++ instances of wrapped classes. + +

Classes

+ +

Class instance_holder

+ +

instance_holder is an abstract base class whose + concrete derived classes hold C++ class instances within their + Python object wrappers. To allow multiple inheritance in Python + from C++ class wrappers, each such Python object contains a chain + of instance_holders. When an __init__ + function for a wrapped C++ class is invoked, a new + instance_holder instance is created and installed in + the Python object using its install() + function. Each concrete class derived from + instance_holder must provide a holds() + implementation which allows Boost.Python to query it for the + type(s) it is holding. In order to support the held type's wrapped + constructor(s), the class must also provide constructors that can + accept an initial PyObject* argument referring to the + owning Python object, and which forward the rest of their + arguments to the constructor of the held type. The initial + argument is needed to enable virtual function overriding in + Python, and may be ignored, depending on the specific + instance_holder subclass. + +

Class instance_holder + synopsis

+
+namespace boost { namespace python
+{
+  class instance_holder : noncopyable
+  {
+   public:
+      // destructor
+      virtual ~instance_holder();
+
+      // instance_holder modifiers
+      void install(PyObject* inst) throw();
+
+      // instance_holder observers
+      virtual void* holds(type_info) = 0;
+  };
+}}
+
+ +

Class instance_holder + destructor

+
+virtual ~instance_holder();
+
+ +
+
Effects: destroys the object +
+ +

Class + instance_holder modifiers

+
+void install(PyObject* inst) throw();
+
+ +
+
Requires: inst is a Python instance of a + wrapped C++ class type, or is a type derived from a wrapped C++ + class type. +
Effects: installs the new instance at the head of the + Python object's chain of held instances. +
Throws: nothing +
+ +

Class instance_holder + observers

+
+virtual void* holds(type_info x) = 0;
+
+ +
+
Returns: A pointer to an object of the type described + by x if *this contains such an object, + 0 otherwise. +
+ +

Example

+ +The following is a simplified version of the instance holder template +used by Boost.Python to wrap classes held by smart pointers: +
+template <class SmartPtr, class Value>
+struct pointer_holder : instance_holder
+{
+   // construct from the SmartPtr type
+   pointer_holder(SmartPtr p)
+       :m_p(p)
+
+   // Forwarding constructors for the held type
+   pointer_holder(PyObject*)
+       :m_p(new Value())
+   {
+   }
+
+   template<class A0>
+   pointer_holder(PyObject*,A0 a0)
+       :m_p(new Value(a0))
+   {
+   }
+
+   template<class A0,class A1>
+   pointer_holder(PyObject*,A0 a0,A1 a1)
+       :m_p(new Value(a0,a1))
+   {
+   }
+   ...
+
+ private: // required holder implementation
+   void* holds(type_info dst_t)
+   {
+       // holds an instance of the SmartPtr type...
+       if (dst_t == python::type_id<SmartPtr>())
+           return &this->m_p;
+
+       // ...and an instance of the SmartPtr's element_type, if the
+       // pointer is non-null
+       return python::type_id<Value>() == dst_t ? &*this->m_p : 0;
+   }
+
+ private: // data members
+   SmartPtr m_p;
+};
+
+ +

Revised + + 13 November, 2002 + + + +

© Copyright Dave Abrahams 2002. + + + diff --git a/libs/python/doc/v2/iterator.html b/libs/python/doc/v2/iterator.html new file mode 100644 index 0000000000..3557ffb9af --- /dev/null +++ b/libs/python/doc/v2/iterator.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + Boost.Python - <boost/python/iterator.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/iterator.hpp>

+
+


+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class template + iterator
+ +
+
+
Class + iterator synopsis
+ +
Class template + iterator constructor
+
+
+
+ +
+
Class template + iterators
+ +
+
+
Class + iterators synopsis
+ +
Class template + iterators nested types
+ +
Class template + iterators static functions
+
+
+
+
+ +
Functions
+ +
+
+
range
+
+
+ +
Examples
+
+
+ +

Introduction

+ +

<boost/python/iterator.hpp> provides types and + functions for creating Python + iterators from C++ Containers and Iterators. Note + that if your class_ supports random-access iterators, + implementing __getitem__ + (also known as the Sequence Protocol) may serve you better than using + this facility: Python will automatically create an iterator type for you + (see iter()), + and each access can be range-checked, leaving no possiblity of accessing + through an invalidated C++ iterator.

+ +

Classes

+ +

Class Template iterator

+ +

Instances of iterator<C,P> hold a reference to a + callable Python object which, when invoked from Python, expects a single + argument c convertible to C and creates a + Python iterator that traverses [c.begin(), + c.end()). The optional CallPolicies P can be used to + control how elements are returned during iteration.

+ +

In the table below, c is an instance of + Container.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Template ParameterRequirementsSemanticsDefault
Container[c.begin(),c.end()) is a valid Iterator range.The result will convert its argument to c and call + c.begin() and c.end() to acquire iterators. + To invoke Container's const + begin() and end() functions, make it + const.
NextPoliciesA default-constructible model of CallPolicies.Applied to the resulting iterators' next() + method.An unspecified model of CallPolicies which + always makes a copy of the result of deferencing the underlying C++ + iterator
+ +

Class Template iterator + synopsis

+
+namespace boost { namespace python
+{
+  template <class Container
+             , class NextPolicies = unspecified>
+  struct iterator : object
+  {
+      iterator();
+  };
+}}
+
+ +

Class Template iterator + constructor

+
+iterator()
+
+ +
+
Effects:
+ +
+ Initializes its base class with the result of: +
+range<NextPolicies>(&iterators<Container>::begin, &iterators<Container>::end)
+
+
+ +
Postconditions: this->get() points to a + Python callable object which creates a Python iterator as described + above.
+ +
Rationale: Provides an easy way to create iterators for the + common case where a C++ class being wrapped provides + begin() and end().
+
+ + +

Class Template + iterators

+ +

A utility class template which provides a way to reliably call its + argument's begin() and end() member functions. + Note that there is no portable way to take the address of a member + function of a C++ standard library container, so + iterators<> can be particularly helpful when wrapping + them.

+ +

In the table below, x is an instance of + C.

+ + + + + + + + + + + + + + + + + + + +
Required Valid ExpressionType
x.begin()Convertible to C::const_iterator if C + is a const type; convertible to C::iterator + otherwise.
x.end()Convertible to C::const_iterator if C + is a const type; convertible to C::iterator + otherwise.
+ +

Class Template iterators + synopsis

+
+namespace boost { namespace python
+{
+  template <class C>
+  struct iterators
+  {
+      typedef typename C::[const_]iterator iterator;
+      static iterator begin(C& x);
+      static iterator end(C& x);
+  };
+}}
+
+
+ +

Class Template iterators nested + types

+ If C is a const type, +
+typedef typename C::const_iterator iterator;
+
+ Otherwise: +
+typedef typename C::iterator iterator;
+
+ +

Class Template iterators static + functions

+
+static iterator begin(C&);
+
+ +
+
Returns: x.begin()
+
+
+static iterator end(C&);
+
+ +
+
Returns: x.end()
+
+ + +

Functions

+
+template <class NextPolicies, class Target, class Accessor1, class Accessor2>
+object range(Accessor1 start, Accessor2 finish);
+
+template <class NextPolicies, class Accessor1, class Accessor2>
+object range(Accessor1 start, Accessor2 finish);
+
+template <class Accessor1, class Accessor2>
+object range(Accessor1 start, Accessor2 finish);
+
+ +
+
Requires: NextPolicies is a + default-constructible model of CallPolicies.
+ +
Effects:
+ +
+
+
The first form creates a Python callable object which, when + invoked, converts its argument to a Target object + x, and creates a Python iterator which traverses + [bind(start,_1)(x)bind(finish,_1)(x)), + applying NextPolicies to the iterator's + next() function.
+ +
The second form is identical to the first, except that + Target is deduced from Accessor1 as + follows:
+ +
+
    +
  1. If Accessor1 is a function type, + Target is the type of its first argument.
  2. + +
  3. If Accessor1 is a data member pointer of the + form R (T::*), Target is + identical to T.
  4. + +
  5. If Accessor1 is a member function pointer of + the form + R (T::*)(arguments...)  + cv-opt, where cv-opt is an optional + cv-qualifier, Target is identical to + T.
  6. +
+
+ +
The third form is identical to the second, except that + NextPolicies is an unspecified model of CallPolicies which + always makes a copy of the result of deferencing the underlying C++ + iterator
+
+
+ +
Rationale: The use of boost::bind() allows C++ iterators + to be accessed through functions, member functions or data member + pointers. Customization of NextPolicies (e.g. using + return_internal_reference) + is useful when it is expensive to copy sequence elements of a wrapped + class type. Customization of Target is useful when + Accessor1 is a function object, or when a base class of + the intended target type would otherwise be deduced.
+
+ +

Examples

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+
+#include <vector>
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(demo)
+{
+    class_<std::vector<double> >("dvec")
+        .def("__iter__", iterator<std::vector<double> >())
+        ;
+}
+
+ A more comprehensive example can be found in: + +
+
libs/python/test/iterator.cpp
+ +
libs/python/test/input_iterator.cpp
+ +
libs/python/test/input_iterator.py
+ +
+
+

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/list.html b/libs/python/doc/v2/list.html new file mode 100644 index 0000000000..e347ae4617 --- /dev/null +++ b/libs/python/doc/v2/list.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + Boost.Python - <boost/python/list.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/list.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class list
+ +
+
+
Class list + synopsis
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

Exposes a TypeWrapper for the Python + list + type.

+ +

Classes

+ +

Class list

+ +

Exposes the mapping + protocol of Python's built-in list type. The semantics + of the constructors and member functions defined below can be fully + understood by reading the TypeWrapper concept + definition. Since list is publicly derived from object, the public object + interface applies to list instances as well.

+ +

Class list + synopsis

+
+namespace boost { namespace python
+{
+  class list : public object
+  {
+   public:
+      list(); // new list
+
+      template <class T>
+      explicit list(T const& sequence);
+
+      template <class T>
+      void append(T const& x);
+
+      template <class T>
+      long count(T const& value) const;
+
+      template <class T>
+      void extend(T const& x);
+
+      template <class T>
+      long index(T const& x) const;
+
+      template <class T>
+      void insert(object const& index, T const& x); // insert object before index
+
+      object pop(); // remove and return item at index (default last)
+      object pop(long index);
+      object pop(object const& index);
+
+      template <class T>
+      void remove(T const& value);
+
+      void reverse(); // reverse *IN PLACE*
+
+      void sort(); //  sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
+
+      template <class T>
+      void sort(T const& value);
+  };
+}}
+
+ +

Example

+
+using namespace boost::python;
+
+// Return the number of zeroes in the list
+long zeroes(list l)
+{
+   return l.count(0);
+}
+
+ +

Revised 1 October, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/long.html b/libs/python/doc/v2/long.html new file mode 100644 index 0000000000..08ceb3bd5c --- /dev/null +++ b/libs/python/doc/v2/long.html @@ -0,0 +1,119 @@ + + + + + + + + + + + + Boost.Python - <boost/python/long.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/long.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class long_
+ +
+
+
Class long_ + synopsis
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

Exposes a TypeWrapper for the Python + long + integer type.

+ +

Classes

+ +

Class long_

+ +

Exposes the numeric type + protocol of Python's built-in long type. The semantics + of the constructors and member functions defined below can be fully + understood by reading the TypeWrapper concept + definition. Since long_ is publicly derived from object, the public object + interface applies to long_ instances as well.

+ +

Class long_ + synopsis

+
+namespace boost { namespace python
+{
+  class long_ : public object
+  {
+   public:
+      long_(); // new long_
+
+      template <class T>
+      explicit long_(T const& rhs);
+
+      template <class T, class U>
+      long_(T const& rhs, U const& base);
+  };
+}}
+
+ +

Example

+
+namespace python = boost::python;
+
+// compute a factorial without overflowing
+python::long_ fact(long n)
+{
+   if (n == 0)
+      return python::long_(1);
+   else
+      return n * fact(n - 1);
+}
+
+ +

Revised 1 October, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/lvalue_from_pytype.html b/libs/python/doc/v2/lvalue_from_pytype.html new file mode 100644 index 0000000000..d27c57d0cf --- /dev/null +++ b/libs/python/doc/v2/lvalue_from_pytype.html @@ -0,0 +1,301 @@ + + + + + + + + + + + + Boost.Python - <boost/python/lvalue_from_python.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/lvalue_from_pytype.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class Template + lvalue_from_pytype
+ +
+
+
Class Template + lvalue_from_pytype synopsis
+ +
Class Template + lvalue_from_pytype constructor
+
+
+
+ +
+
Class Template + extract_identity
+ +
+
+
Class Template + extract_identity synopsis
+ +
Class Template + extract_identity static functions
+
+
+ +
Class Template + extract_member
+ +
+
+
Class Template + extract_member synopsis
+ +
Class Template + extract_member static functions
+
+
+
+
+ +
Example
+
+
+ +

Introduction

+ <boost/python/lvalue_from_pytype.hpp> supplies a + facility for extracting C++ objects from within Python instances of a + given type. This is typically useful for dealing with "traditional" + Python extension types. + +

Classes

+ +

Class template + lvalue_from_pytype

+ +

Class template lvalue_from_pytype will register + from_python converters which, given an object of the given Python type, + can extract references and pointers to a particular C++ type. Its + template arguments are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ lvalue_from_pytype Requirements
+ In the table below, x denotes an object of type + PythonObject& +
ParameterRequirementsSemantics
Extractora model of Extractor whose execute + function returns a reference type.Extracts the lvalue from the Python object once its type has been + confirmed
python_typeA compile-time constant PyTypeObject*The Python type of instances convertible by this converter. + Python subtypes are also convertible.
+ +

Class template + lvalue_from_pytype synopsis

+
+namespace boost { namespace python
+{
+   template <class Extractor, PyTypeObject const* python_type>
+   struct lvalue_from_pytype
+   {
+       lvalue_from_pytype();
+   };
+}}
+
+ +

Class template + lvalue_from_pytype constructor

+
+lvalue_from_pytype();
+
+ +
+
Effects: Registers converters which can convert Python + objects of the given type to lvalues of the type returned by + Extractor::execute.
+
+ +

Class template + extract_identity

+ +

extract_identity is a model of Extractor which can be used in the + common case where the C++ type to be extracted is the same as the Python + object type.

+ +

Class template + extract_identity synopsis

+
+namespace boost { namespace python
+{
+   template <class InstanceType>
+   struct extract_identity
+   {
+      static InstanceType& execute(InstanceType& c);
+   };
+}}
+
+ +

Class template + extract_identity static functions

+
+InstanceType& execute(InstanceType& c);
+
+ +
+
Returns: c
+
+ +

Class template + extract_member

+ +

extract_member is a model of Extractor which can be used in the + common case in the common case where the C++ type to be extracted is a + member of the Python object.

+ +

Class template + extract_member synopsis

+
+namespace boost { namespace python
+{
+   template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
+   struct extract_member
+   {
+      static MemberType& execute(InstanceType& c);
+   };
+}}
+
+ +

Class template + extract_member static functions

+
+static MemberType& execute(InstanceType& c);
+
+ +
+
Returns: c.*member
+
+ +

Example

+ This example presumes that someone has implemented the standard noddy example + module from the Python documentation, and we want to build a module + which manipulates Noddys. Since + noddy_NoddyObject is so simple that it carries no + interesting information, the example is a bit contrived: it assumes you + want to keep track of one particular object for some reason. This module + would have to be dynamically linked to the module which defines + noddy_NoddyType. + +

C++ module definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/handle.hpp>
+#include <boost/python/borrowed.hpp>
+#include <boost/python/lvalue_from_pytype.hpp>
+
+// definition lifted from the Python docs
+typedef struct {
+   PyObject_HEAD
+} noddy_NoddyObject;
+
+using namespace boost::python;
+static handle<noddy_NoddyObject> cache;
+
+bool is_cached(noddy_NoddyObject* x)
+{
+   return x == cache.get();
+}
+
+void set_cache(noddy_NoddyObject* x)
+{
+   cache = handle<noddy_NoddyObject>(borrowed(x));
+}
+
+BOOST_PYTHON_MODULE(noddy_cache)
+{
+   def("is_cached", is_cached);
+   def("set_cache", set_cache);
+
+   // register Noddy lvalue converter
+   lvalue_from_pytype<extract_identity<noddy_NoddyObject>,&noddy_NoddyType>();
+}
+
+ +

Python code

+
+>>> import noddy
+>>> n = noddy.new_noddy()
+>>> import noddy_cache
+>>> noddy_cache.is_cached(n)
+0
+>>> noddy_cache.set_cache(n)
+>>> noddy_cache.is_cached(n)
+1
+>>> noddy_cache.is_cached(noddy.new_noddy())
+0
+
+ +

Revised + + 20 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/make_function.html b/libs/python/doc/v2/make_function.html new file mode 100644 index 0000000000..3913672195 --- /dev/null +++ b/libs/python/doc/v2/make_function.html @@ -0,0 +1,210 @@ + + + + + + + + + + + + Boost.Python - <boost/python/make_function.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/make_function.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
make_function
+ +
make_constructor
+
+
+ +
Example
+
+
+ +

Introduction

+ +

make_function() and + make_constructor() are + the functions used internally by def() and class_<>::def() to produce Python + callable objects which wrap C++ functions and member functions.

+ +

Functions

+
+template <class F>
+object make_function(F f)
+
+template <class F, class Policies>
+object make_function(F f, Policies const& policies)
+
+template <class F, class Policies, class KeywordsOrSignature>
+object make_function(F f, Policies const& policies, KeywordsOrSignature const& ks)
+
+template <class F, class Policies, class Keywords, class Signature>
+object make_function(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
+
+ +
+
Requires: F is a function pointer or member + function pointer type. If policies are supplied, it must + be a model of CallPolicies. If + kewords are supplied, it must be the result of a keyword-expression + specifying no more arguments than the arity of f.
+ +
Effects: Creates a Python callable object which, when called + from Python, converts its arguments to C++ and calls f. If + F is a pointer-to-member-function type, the target + object of the function call (*this) will be taken + from the first Python argument, and subsequent Python arguments + will be used as the arguments + to f.
    +
  • If policies are supplied, it + will be applied to the function as described here. +
  • If keywords are + supplied, the keywords will be applied in order to the final + arguments of the resulting function. +
  • If Signature + is supplied, it should be an instance of an MPL front-extensible + sequence representing the function's return type followed by + its argument types. Pass a Signature when wrapping + function object types whose signatures can't be deduced, or when + you wish to override the types which will be passed to the + wrapped function. +
+ +
Returns: An instance of object which holds the new Python + callable object.
+ +
Caveats: An argument of pointer type may + be 0 if None is passed from Python. + An argument type which is a constant reference may refer to a + temporary which was created from the Python object for just the + duration of the call to the wrapped function, for example + a std::vector conjured up by the conversion process + from a Python list. Use a non-const reference + argument when a persistent lvalue is required. +
+ +
+template <class T, class ArgList, class Generator>
+object make_constructor();
+ 
+template <class ArgList, class Generator, class Policies>
+object make_constructor(Policies const& policies)
+
+ +
+
Requires: T is a class type. + Policies is a model of CallPolicies. ArgList is an MPL sequence of C++ argument + types (A1, A2,... AN) such that if + a1, a2... aN are objects of type + A1, A2,... AN respectively, the expression new + Generator::apply<T>::type(a1, a2... aN) + is valid. Generator is a model of HolderGenerator.
+ +
Effects: Creates a Python callable object which, when called + from Python, expects its first argument to be a Boost.Python extension + class object. It converts its remaining its arguments to C++ and passes + them to the constructor of a dynamically-allocated + Generator::apply<T>::type object, which is then + installed in the extension class object. In the second form, the + policies are applied to the arguments and result (None) + of the Python callable object
+ +
Returns: An instance of object which holds the new Python + callable object.
+
+ +

Example

+ +

C++ function exposed below returns a callable object wrapping one of + two functions.

+
+#include <boost/python/make_function.hpp>
+#include <boost/python/module.hpp>
+
+char const* foo() { return "foo"; }
+char const* bar() { return "bar"; }
+
+using namespace boost::python;
+object choose_function(bool selector)
+{
+    if (selector)
+        return boost::python::make_function(foo);
+    else
+        return boost::python::make_function(bar);
+}
+
+BOOST_PYTHON_MODULE(make_function_test)
+{
+    def("choose_function", choose_function);
+}
+
+ It can be used this way in Python: +
+>>> from make_function_test import *
+>>> f = choose_function(1)
+>>> g = choose_function(0)
+>>> f()
+'foo'
+>>> g()
+'bar'
+
+ +

+ + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/manage_new_object.html b/libs/python/doc/v2/manage_new_object.html new file mode 100644 index 0000000000..57efb41374 --- /dev/null +++ b/libs/python/doc/v2/manage_new_object.html @@ -0,0 +1,145 @@ + + + + + + + + + + + + Boost.Python - <boost/python/manage_new_object.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/manage_new_object.hpp>

+
+
+ +

Contents

+ +
+
Classes
+ +
+
+
Class + manage_new_object
+ +
+
+
Class + manage_new_object synopsis
+ +
Class + manage_new_object metafunctions
+
+
+
+
+ +
Example
+
+
+ +

Classes

+ +

Class + manage_new_object

+ +

manage_new_object is a model of ResultConverterGenerator + which can be used to wrap C++ functions which return a pointer to an + object allocated with a new-expression, and expect the caller to + take responsibility for deleting that object.

+ +

Class + manage_new_object synopsis

+
+namespace boost { namespace python
+{
+    struct manage_new_object
+    {
+        template <class T> struct apply;
+    };
+}}
+
+ +

Class + manage_new_object metafunctions

+
+template <class T> struct apply
+
+ +
+
Requires: T is U* for some + U.
+ +
Returns: typedef to_python_indirect<T> + type;
+
+ +

Example

+ +

In C++:

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/manage_new_object.hpp>
+#include <boost/python/return_value_policy.hpp>
+
+
+struct Foo {
+   Foo(int x) : x(x){}
+   int get_x() { return x; }
+   int x;
+};
+
+Foo* make_foo(int x) { return new Foo(x); }
+
+// Wrapper code
+using namespace boost::python;
+BOOST_PYTHON_MODULE(my_module)
+{
+    def("make_foo", make_foo, return_value_policy<manage_new_object>())
+    class_<Foo>("Foo")
+        .def("get_x", &Foo::get_x)
+        ;
+}
+
+ In Python: +
+>>> from my_module import *
+>>> f = make_foo(3)     # create a Foo object
+>>> f.get_x()
+3
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/module.html b/libs/python/doc/v2/module.html new file mode 100644 index 0000000000..353523cb6f --- /dev/null +++ b/libs/python/doc/v2/module.html @@ -0,0 +1,110 @@ + + + + + + Boost.Python - <boost/python/module.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header <boost/python/module.hpp>

+
+
+ +

Contents

+ +
+
Introduction + +
Macros + +
+
+
BOOST_PYTHON_MODULE +
+ +
Example(s) +
+
+ +

Introduction

+ +

This header provides the basic facilities needed to create a + Boost.Python extension module. + +

Macros

+ +

BOOST_PYTHON_MODULE(name) + is used to declare Python + module initialization functions. The name argument must + exactly match the name of the module to be initialized, and must conform to + Python's identifier naming + rules. Where you would normally write +

+extern "C" void initname()
+{
+   ...
+}
+
+ Boost.Python modules should be initialized with +
+BOOST_PYTHON_MODULE(name)
+{
+   ...
+}
+
+ +This macro generates two functions in the scope where it is used: +extern "C" void initname(), +and void init_module_name(), whose body must +follow the macro invocation. init_name passes +init_module_name to handle_exception() so +that any C++ exceptions generated are safely processeed. During the +body of init_name, the current scope refers to the module +being initialized. + +

Example(s)

+ +

C++ module definition: +

+#include <boost/python/module.hpp>
+
+BOOST_PYTHON_MODULE(xxx)
+{
+    throw "something bad happened"
+}
+
+ +Interactive Python: +
+>>> import xxx
+Traceback (most recent call last):
+  File "", line 1, in ?
+RuntimeError: Unidentifiable C++ Exception
+
+ +

Revised + + 13 November, 2002 + + + +

© Copyright Dave + Abrahams 2002. 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)

+ diff --git a/libs/python/doc/v2/numeric.html b/libs/python/doc/v2/numeric.html new file mode 100644 index 0000000000..eaa390af4d --- /dev/null +++ b/libs/python/doc/v2/numeric.html @@ -0,0 +1,276 @@ + + + + + + + + + + + + Boost.Python - <boost/python/numeric.hpp> + + + + + + + + + +
+

+

+
+

Boost.Python

+ +

Header <boost/python/numeric.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class array
+ +
+
+
Class array + synopsis
+ +
Class array + observer functions
+ +
Class array static + functions
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

Exposes a TypeWrapper for the Python + array + type.

+ +

Classes

+ +

Class array

+ +

Provides access to the array types of Numerical Python's Numeric and NumArray modules. With + the exception of the functions documented below, the semantics of the constructors and + member functions defined below can be fully understood by reading the + TypeWrapper concept + definition. Since array is publicly derived from + object, the public + object interface applies to array instances as well.

+ +

The default behavior is + to use numarray.NDArray as the associated Python type if the + numarray module is installed in the default location. + Otherwise it falls back to use Numeric.ArrayType. If neither + extension module is installed, overloads of wrapped C++ functions with + numeric::array parameters will never be matched, and other + attempted uses of numeric::array will raise an appropriate Python exception. The + associated Python type can be set manually using the set_module_and_type(...) static + function.

+ +

Class + array synopsis

+
+namespace boost { namespace python { namespace numeric
+{
+   class array : public object
+   {
+    public:
+      object astype();
+      template <class Type>
+      object astype(Type const& type_);
+
+      template <class Type>
+      array new_(Type const& type_) const;
+
+      template <class Sequence> 
+      void resize(Sequence const& x);
+      void resize(long x1);
+      void resize(long x1, long x2);
+      ...
+      void resize(long x1, long x2,...long xn);
+
+      template <class Sequence> 
+      void setshape(Sequence const& x);
+      void setshape(long x1);
+      void setshape(long x1, long x2);
+      ...
+      void setshape(long x1, long x2,...long xn);
+
+      template <class Indices, class Values>
+      void put(Indices const& indices, Values const& values);
+
+      template <class Sequence>
+      object take(Sequence const& sequence, long axis = 0);
+
+      template <class File>
+      void tofile(File const& f) const;
+
+      object factory();
+      template <class Sequence>
+      object factory(Sequence const&);
+      template <class Sequence, class Typecode>
+      object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
+      template <class Sequence, class Typecode, class Type>
+      object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
+      template <class Sequence, class Typecode, class Type, class Shape>
+      object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
+
+      template <class T1>
+      explicit array(T1 const& x1);
+      template <class T1, class T2>
+      explicit array(T1 const& x1, T2 const& x2);
+      ...
+      template <class T1, class T2,...class Tn>
+      explicit array(T1 const& x1, T2 const& x2,...Tn const& xn);
+
+      static void set_module_and_type();
+      static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
+      static void get_module_name();
+
+      object argmax(long axis=-1);
+
+      object argmin(long axis=-1);
+
+      object argsort(long axis=-1);
+
+      void byteswap();
+
+      object copy() const;
+
+      object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const;
+
+      void info() const;
+
+      bool is_c_array() const;
+      bool isbyteswapped() const;
+      void sort();
+      object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
+      object type() const;
+      char typecode() const;
+      
+      object getflat() const;
+      long getrank() const;
+      object getshape() const;
+      bool isaligned() const;
+      bool iscontiguous() const;
+      long itemsize() const;
+      long nelements() const;
+      object nonzero() const;
+   
+      void ravel();
+   
+      object repeat(object const& repeats, long axis=0);
+   
+      void setflat(object const& flat);
+   
+      void swapaxes(long axis1, long axis2);
+   
+      str tostring() const;
+   
+      void transpose(object const& axes = object());
+   
+      object view() const;
+  };
+}}}
+
+ +

Class + array observer functions

+
+object factory();
+template <class Sequence>
+object factory(Sequence const&);
+template <class Sequence, class Typecode>
+object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
+template <class Sequence, class Typecode, class Type>
+object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
+template <class Sequence, class Typecode, class Type, class Shape>
+object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
+
These functions map to the underlying array type's array() +function family. They are not called "array" because of the C++ +limitation that you can't define a member function with the same name as its +enclosing class. +
+template <class Type>
+array new_(Type const&) const;
+
This function maps to the underlying array type's new() +function. It is not called "new" because that is a keyword in +C++. + +

Class + array static functions

+
+static void set_module_and_type(char const* package_path, char const* type_name);
+static void set_module_and_type();
+
+ +
+
Requires: package_path and + type_name, if supplied, is an ntbs.
+ +
Effects: The first form sets the package path of the module + that supplies the type named by type_name to + package_path. The second form restores the default search behavior. The associated Python type + will be searched for only the first time it is needed, and thereafter the + first time it is needed after an invocation of + set_module_and_type.
+
+
+static std::string get_module_name()
+
+ +
+
Effects: Returns the name of the module containing the class + that will be held by new numeric::array instances.
+
+ +

Example

+
+#include <boost/python/numeric.hpp>
+#include <boost/python/tuple.hpp>
+
+// sets the first element in a 2d numeric array
+void set_first_element(numeric::array& y, double value)
+{
+    y[make_tuple(0,0)] = value;
+}
+
+ +

Revised 07 October, 2006

+ +

© Copyright Dave + Abrahams 2002-2006.

+ + diff --git a/libs/python/doc/v2/object.html b/libs/python/doc/v2/object.html new file mode 100644 index 0000000000..8df8ef5f8f --- /dev/null +++ b/libs/python/doc/v2/object.html @@ -0,0 +1,1121 @@ + + + + + + + + + + + + Boost.Python - <boost/python/object.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/object.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Types
+ +
+
+
slice_nil
+
+
+ +
Classes
+ +
+
+
Class + const_attribute_policies
+ +
+
+
Class + const_attribute_policies synopsis
+ +
Class + const_attribute_policies static functions
+
+
+ +
Class + attribute_policies
+ +
+
+
Class + attribute_policies synopsis
+ +
Class + attribute_policies static functions
+
+
+ +
Class + const_objattribute_policies
+ +
+
+
Class + const_objattribute_policies synopsis
+ +
Class + const_objattribute_policies static functions
+
+
+ +
Class + objattribute_policies
+ +
+
+
Class + objattribute_policies synopsis
+ +
Class + objattribute_policies static functions
+
+
+ +
Class + const_item_policies
+ +
+
+
Class + const_item_policies synopsis
+ +
Class + const_item_policies static functions
+
+
+ +
Class + item_policies
+ +
+
+
Class + item_policies synopsis
+ +
Class + item_policies static functions
+
+
+ +
Class + const_slice_policies
+ +
+
+
Class + const_slice_policies synopsis
+ +
Class + const_slice_policies static functions
+
+
+ +
Class + slice_policies
+ +
+
+
Class + slice_policies synopsis
+ +
Class + slice_policies static functions
+
+
+ +
Class + object_operators
+ +
+
+
Class + object_operators synopsis
+ +
Class + object_operators observer functions
+
+
+ +
Class object
+ +
+
+
Class object + synopsis
+ +
Class object + constructors and destructor
+ +
Class template + object modifier functions
+ +
Class template + object observer functions
+
+
+ +
Class template + proxy
+ +
+
+
Class template + proxy synopsis
+ +
Class template + proxy modifier functions
+ +
Class template + proxy observer functions
+
+
+
+
+ +
Functions
+ +
+
+
del
+ +
comparisons
+ +
binary operations
+ +
assignment operations
+ +
+ +
+
operators
+
+ +
+
len()
+
+
+ +
Example
+
+
+ +

Introduction

+ +

Exposes the generic Python object wrapper class object, + and related classes. In order to avoid some potenential problems with + argument-dependent lookup and the generalized operators defined on + object, all these facilities are defined in + namespace boost::python::api, and object + is imported into namespace boost::python with a + using-declaration.

+ +

Types

+ +

+
+class slice_nil;
+static const _ = slice_nil();
+
+ A type that can be used to get the effect of leaving out an index in a + Python slice expression: +
+>>> x[:-1]
+>>> x[::-1]
+
+ C++ equivalent: +
+x.slice(_,-1)
+x[slice(_,_,-1)]
+
+ +

Classes

+ + +

Class + const_attribute_policies

+ +

The policies which are used for proxies representing an attribute + access to a const object.

+ +

Class + const_attribute_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct const_attribute_policies
+  {
+      typedef char const* key_type;
+      static object get(object const& target, char const* key);
+  };
+}}}
+
+ +

Class + const_attribute_policies static functions

+
+static object get(object const& target, char const* key);
+
+ +
+
Requires: key is an ntbs.
+ +
Effects: accesses the attribute of target named + by key.
+ +
Returns: An object managing the result of the + attribute access.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ +

Class + attribute_policies

+ +

The policies which are used for proxies representing an attribute + access to a mutable object.

+ +

Class + attribute_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct attribute_policies : const_attribute_policies
+  {
+      static object const& set(object const& target, char const* key, object const& value);
+      static void del(object const&target, char const* key);
+  };
+}}}
+
+ +

Class + attribute_policies static functions

+
+static object const& set(object const& target, char const* key, object const& value);
+
+ +
+
Requires: key is an ntbs.
+ +
Effects: sets the attribute of target named by + key to value.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+
+static void del(object const&target, char const* key);
+
+ +
+
Requires: key is an ntbs.
+ +
Effects: deletes the attribute of target named + by key.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ + + +

Class + const_objattribute_policies

+ +

The policies which are used for proxies representing an attribute + access to a const object when the attribute name is + given as a const object.

+ +

Class + const_objattribute_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct const_objattribute_policies
+  {
+      typedef object const& key_type;
+      static object get(object const& target, object const& key);
+  };
+}}}
+
+ +

Class + const_objattribute_policies static functions

+
+static object get(object const& target, object const& key);
+
+ +
+
Requires: key is an object + holding a string.
+ +
Effects: accesses the attribute of target named + by key.
+ +
Returns: An object managing the result of the + attribute access.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ +

Class + objattribute_policies

+ +

The policies which are used for proxies representing an attribute + access to a mutable object when the attribute name is + given as a const object.

+ +

Class + objattribute_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct objattribute_policies : const_objattribute_policies
+  {
+      static object const& set(object const& target, object const& key, object const& value);
+      static void del(object const&target, object const& key);
+  };
+}}}
+
+ +

Class + objattribute_policies static functions

+
+static object const& set(object const& target, object const& key, object const& value);
+
+ +
+
Requires: key is an object + holding a string.
+ +
Effects: sets the attribute of target named by + key to value.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+
+static void del(object const&target, object const& key);
+
+ +
+
Requires: key is an object + holding a string.
+ +
Effects: deletes the attribute of target named + by key.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ + + +

Class + const_item_policies

+ +

The policies which are used for proxies representing an item access + (via the Python bracket operators []) to a + const object.

+ +

Class + const_item_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct const_item_policies
+  {
+      typedef object key_type;
+      static object get(object const& target, object const& key);
+  };
+}}}
+
+ +

Class + const_item_policies static functions

+
+static object get(object const& target, object const& key);
+
+ +
+
Effects: accesses the item of target specified + by key.
+ +
Returns: An object managing the result of the + item access.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ +

Class + item_policies

+ +

The policies which are used for proxies representing an item access + (via the Python bracket operators []) to a mutable + object.

+ +

Class + item_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct item_policies : const_item_policies
+  {
+      static object const& set(object const& target, object const& key, object const& value);
+      static void del(object const& target, object const& key);
+  };
+}}}
+
+ +

Class + item_policies static functions

+
+static object const& set(object const& target, object const& key, object const& value);
+
+ +
+
Effects: sets the item of target specified by + key to value.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+
+static void del(object const& target, object const& key);
+
+ +
+
Effects: deletes the item of target specified + by key.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ + + +

Class + const_slice_policies

+ +

The policies which are used for proxies representing an slice access + (via the Python slice notation + [x:y]) to a + const object.

+ +

Class + const_slice_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct const_slice_policies
+  {
+      typedef std::pair<handle<>, handle<> > key_type;
+      static object get(object const& target, key_type const& key);
+  };
+}}}
+
+ +

Class + const_slice_policies static functions

+
+static object get(object const& target, key_type const& key);
+
+ +
+
Effects: accesses the slice of target specified + by key.
+ +
Returns: An object managing the result of the + slice access.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ +

Class + slice_policies

+ +

The policies which are used for proxies representing an slice access + to a mutable object.

+ +

Class + slice_policies synopsis

+
+namespace boost { namespace python { namespace api
+{
+  struct slice_policies : const_slice_policies
+  {
+      static object const& set(object const& target, key_type const& key, object const& value);
+      static void del(object const& target, key_type const& key);
+  };
+}}}
+
+ +

Class + slice_policies static functions

+
+static object const& set(object const& target, key_type const& key, object const& value);
+
+ +
+
Effects: sets the slice of target specified by + key to value.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+
+static void del(object const& target, key_type const& key);
+
+ +
+
Effects: deletes the slice of target specified + by key.
+ +
Throws: error_already_set if a + Python exception is raised.
+
+ + +

Class template + object_operators<U>

+ +

This is the base class of object and its + proxy template used to supply common interface: member + functions, and operators which must be defined within the class body. Its + template parameter U is expected to be a class derived from + object_operators<U>. In practice users should never + use this class directly, but it is documented here because it supplies + important interface to object and its proxies.

+ +

Class template + object_operators synopsis

+
+namespace boost { namespace python { namespace api
+{
+  template <class U>
+  class object_operators
+  {
+   public:
+      // function call
+      //
+      object operator()() const;
+
+      template <class A0>
+      object operator()(A0 const&) const;
+      template <class A0, class A1>
+      object operator()(A0 const&, A1 const&) const;
+      ...
+      template <class A0, class A1,...class An>
+      object operator()(A0 const&, A1 const&,...An const&) const;
+
+      detail::args_proxy operator* () const; 
+      object operator()(detail::args_proxy const &args) const; 
+      object operator()(detail::args_proxy const &args, 
+                        detail::kwds_proxy const &kwds) const; 
+
+      // truth value testing
+      //
+      typedef unspecified bool_type;
+      operator bool_type() const;
+
+      // Attribute access
+      //
+      proxy<const_object_attribute> attr(char const*) const;
+      proxy<object_attribute> attr(char const*);
+      proxy<const_object_objattribute> attr(object const&) const;
+      proxy<object_objattribute> attr(object const&);
+
+      // item access
+      //
+      template <class T>
+      proxy<const_object_item> operator[](T const& key) const;
+    
+      template <class T>
+      proxy<object_item> operator[](T const& key);
+
+      // slicing
+      //
+      template <class T, class V>
+      proxy<const_object_slice> slice(T const& start, V const& end) const
+    
+      template <class T, class V>
+      proxy<object_slice> slice(T const& start, V const& end);
+  };
+}}}
+
+ +

Class template + object_operators observer functions

+
+object operator()() const;
+template <class A0>
+object operator()(A0 const&) const;
+template <class A0, class A1>
+object operator()(A0 const&, A1 const&) const;
+...
+template <class A0, class A1,...class An>
+object operator()(A0 const& a1, A1 const& a2,...An const& aN) const;
+
+ +
+
Effects: + call<object>(object(*static_cast<U*>(this)).ptr(), a1, + a2,...aN)
+
+ +
+object operator()(detail::args_proxy const &args) const; 
+
+
+
Effects: + call object with arguments given by the tuple args
+
+
+object operator()(detail::args_proxy const &args, 
+                  detail::kwds_proxy const &kwds) const; 
+
+
+
Effects: + call object with arguments given by the tuple args, and named + arguments given by the dictionary kwds
+
+ + +
+operator bool_type() const;
+
+ +
+
Effects: Tests truth value of *this.
+ +
Returns: + call<object>(object(*static_cast<U*>(this)).ptr(), a1, + a2,...aN)
+
+
+proxy<const_object_attribute> attr(char const* name) const;
+proxy<object_attribute> attr(char const* name);
+
+ +
+
Requires: name is an ntbs.
+ +
Effects: accesses the named attribute of + *this.
+ +
Returns: a proxy object which binds + object(*static_cast<U*>(this)) as its target, and + name as its key.
+
+
+proxy<const_object_objattribute> attr(const object& name) const;
+proxy<object_objattribute> attr(const object& name);
+
+ +
+
Requires: name is a object holding a string.
+ +
Effects: accesses the named attribute of + *this.
+ +
Returns: a proxy object which binds + object(*static_cast<U*>(this)) as its target, and + name as its key.
+
+
+template <class T>
+proxy<const_object_item> operator[](T const& key) const;
+template <class T>
+proxy<object_item> operator[](T const& key);
+
+ +
+
Effects: accesses the item of *this indicated + by key.
+ +
Returns: a proxy object which binds + object(*static_cast<U*>(this)) as its target, and + object(key) as its key.
+
+
+template <class T, class V>
+proxy<const_object_slice> slice(T const& start; start, V const& finish) const
+template <class T, class V>
+proxy<object_slice> slice(T const& start; start, V const& finish);
+
+ +
+
Effects: accesses the slice of *this indicated + by std::make_pair(object(start), object(finish)).
+ +
Returns: a proxy object which binds + object(*static_cast<U*>(this)) as its target, and + std::make_pair(object(start), object(finish)) as its + key.
+
+ + +

Class object

+ +

The intention is that object acts as much like a + Python variable as possible. Thus expressions you'd expect to work + in Python should generally work in the same way from C++. Most of + object's interface is provided by its base class + object_operators<object>, + and the free functions defined in this + header. +

+ +

Class object + synopsis

+
+namespace boost { namespace python { namespace api
+{
+  class object : public object_operators<object>
+  {
+   public:
+      object();
+
+      object(object const&);
+      
+      template <class T>
+      explicit object(T const& x);
+
+      ~object();
+
+      object& operator=(object const&); 
+
+      PyObject* ptr() const;
+
+      bool is_none() const;
+  };
+}}}
+
+ +

Class object + constructors and destructor

+
+object();
+
+ +
+
Effects: Constructs an object managing a reference to the + Python None object.
+ +
Throws: nothing.
+
+
+template <class T>
+explicit object(T const& x);
+
+ +
+
Effects: converts x to python and manages a + reference to it.
+ +
Throws: error_already_set and sets a Python + TypeError exception if no such conversion is + possible.
+
+
+~object();
+
+ +
+
Effects: decrements the reference count of the + internally-held object.
+
+ +

Class object + modifiers

+
+object& operator=(object const& rhs); 
+
+ +
+
Effects: increments the reference count of the object held + by rhs and decrements the reference count of the object + held by *this.
+
+ +

Class object + observers

+
+PyObject* ptr() const;
+
+ +
+
Returns: a pointer to the internally-held Python + object.
+
+ +
+bool is_none() const;
+
+ +
+
Returns: result of (ptr() == Py_None)
+
+ + +

Class template proxy

+ +

This template is instantiated with various Policies described in this + document in order to implement attribute, item, and slice access for + object. It stores an object of type + Policies::key_type.

+ +

Class template proxy + synopsis

+
+namespace boost { namespace python { namespace api
+{
+  template <class Policies>
+  class proxy : public object_operators<proxy<Policies> >
+  {
+   public:
+      operator object() const;
+
+      proxy const& operator=(proxy const&) const;
+      template <class T>
+      inline proxy const& operator=(T const& rhs) const;
+      
+      void del() const;
+
+      template <class R>
+      proxy operator+=(R const& rhs);
+      template <class R>
+      proxy operator-=(R const& rhs);
+      template <class R>
+      proxy operator*=(R const& rhs);
+      template <class R>
+      proxy operator/=(R const& rhs);
+      template <class R>
+      proxy operator%=(R const& rhs);
+      template <class R>
+      proxy operator<<=(R const& rhs);
+      template <class R>
+      proxy operator>>=(R const& rhs);
+      template <class R>
+      proxy operator&=(R const& rhs);
+      template <class R>
+      proxy operator|=(R const& rhs);
+  };
+}}}
+
+ +

Class template proxy + observer functions

+
+operator object() const;
+
+ +
+
Effects: applies + Policies::get(target, key + ) with the proxy's target and key objects.
+
+ +

Class template proxy + modifier functions

+
+proxy const& operator=(proxy const& rhs) const;
+template <class T>
+inline proxy const& operator=(T const& rhs) const;
+
+ +
+
Effects: + Policies::set(target, key + , object(rhs)) with the proxy's target and key + objects.
+
+
+template <class R>
+proxy operator+=(R const& rhs);
+template <class R>
+proxy operator-=(R const& rhs);
+template <class R>
+proxy operator*=(R const& rhs);
+template <class R>
+proxy operator/=(R const& rhs);
+template <class R>
+proxy operator%=(R const& rhs);
+template <class R>
+proxy operator<<=(R const& rhs);
+template <class R>
+proxy operator>>=(R const& rhs);
+template <class R>
+proxy operator&=(R const& rhs);
+template <class R>
+proxy operator|=(R const& rhs);
+
+ +
+
Effects: for a given operator@=, + object(*this) @= rhs;
+
Returns: *this
+
+
+void del() const;
+
+ +
+
Effects: + Policies::del(target, key + ) with the proxy's target and key objects.
+
+ + +

Functions

+
+template <class T>
+void del(proxy<T> const& x);
+
+ +
+
Effects: x.del()
+
+
+
+template<class L,class R> object operator>(L const&l,R const&r);
+template<class L,class R> object operator>=(L const&l,R const&r);
+template<class L,class R> object operator<(L const&l,R const&r);
+template<class L,class R> object operator<=(L const&l,R const&r);
+template<class L,class R> object operator==(L const&l,R const&r);
+template<class L,class R> object operator!=(L const&l,R const&r);
+
+ +
+
Effects: returns the result of applying the operator to + object(l) and object(r), respectively, in + Python.
+
+
+
+template<class L,class R> object operator+(L const&l,R const&r);
+template<class L,class R> object operator-(L const&l,R const&r);
+template<class L,class R> object operator*(L const&l,R const&r);
+template<class L,class R> object operator/(L const&l,R const&r);
+template<class L,class R> object operator%(L const&l,R const&r);
+template<class L,class R> object operator<<(L const&l,R const&r);
+template<class L,class R> object operator>>(L const&l,R const&r);
+template<class L,class R> object operator&(L const&l,R const&r);
+template<class L,class R> object operator^(L const&l,R const&r);
+template<class L,class R> object operator|(L const&l,R const&r);
+
+ +
+
Effects: returns the result of applying the operator to + object(l) and object(r), respectively, in + Python.
+
+
+
+template<class R> object& operator+=(object&l,R const&r);
+template<class R> object& operator-=(object&l,R const&r);
+template<class R> object& operator*=(object&l,R const&r);
+template<class R> object& operator/=(object&l,R const&r);
+template<class R> object& operator%=(object&l,R const&r);
+template<class R> object& operator<<=(object&l,R const&r)
+template<class R> object& operator>>=(object&l,R const&r);
+template<class R> object& operator&=(object&l,R const&r);
+template<class R> object& operator^=(object&l,R const&r);
+template<class R> object& operator|=(object&l,R const&r);
+
+ +
+
Effects: assigns to l the result of applying the + corresponding Python inplace operator to l and + object(r), respectively.
+ +
Returns: l.
+
+ +
+inline long len(object const& obj);
+
+ +
+
Effects: PyObject_Length(obj.ptr())
+
Returns: len() of object.
+
+ +

Example

+ Python code: +
+def sum_items(seq):
+   result = 0
+   for x in seq:
+      result += x
+   return result
+
+ C++ version: +
+object sum_items(object seq)
+{
+   object result = object(0);
+   for (int i = 0; i < len(seq); ++i)
+      result += seq[i];
+   return result;
+}
+
+

Revised + + 15 March, 2010 + +

+ +

© Copyright Dave Abrahams 2008.

+ + diff --git a/libs/python/doc/v2/opaque.html b/libs/python/doc/v2/opaque.html new file mode 100644 index 0000000000..fed1d446f4 --- /dev/null +++ b/libs/python/doc/v2/opaque.html @@ -0,0 +1,138 @@ + + + + + + + + + + + + Boost.Python - <boost/python/opaque_pointer_converter.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/opaque_pointer_converter.hpp>

+
+
+ +

Contents

+ +
+
Classes
+ +
+
+
Class template + opaque<Pointee>
+ +
+
+
Class template + opaque synopsis
+
+
+
+
+ +
Macros
+
+
+
Macro + BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
+
+
+ +
See Also
+
+
+ +

Classes

+ +

Class template + opaque<P>

+ +

opaque<> registers itself as a converter from + Python objects to pointers to undefined types and vice versa.

+ +

Class template + opaque synopsis

+
+namespace boost { namespace python
+{
+    template<class Pointee>
+    struct opaque
+    {
+        opaque();
+    };
+}}
+
+ +

Class template + opaque constructor

+
+opaque();
+
+ +
+
Effects: +
    +
  • Registers the instance as a + lvalue_from_pytype + converter from Python objects into opaque pointers.

    +

    The Python Objects created are named after the type pointed to + by the opaque pointer being wrapped.

  • +
  • Registers the instance as a + to_python_converter + from opaque pointers to Python objects.

  • +
+

If there is already an instance registered by another module, this + instance doesn't try to register again in order to avoid warnings + about multiple registrations.

+ +

Note

+

Normally only a single instance of this class is created for every + Pointee.

+
+
+ +

Macros

+ +

+ Macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)

+

This macro must be used to define specializations of the + type_id function + which can't be instantiated for incomplete types.

+

Note

+

The macro must be invoked in every translation unit which uses the + opaque converter.

+ +

See Also

+

+ return_opaque_pointer +

+ +

Revised + 10 September, 2006 +

+ +

© Copyright 2003..2006 Haufe Mediengruppe. All Rights + Reserved.

+ + + diff --git a/libs/python/doc/v2/operators.html b/libs/python/doc/v2/operators.html new file mode 100644 index 0000000000..69740243fb --- /dev/null +++ b/libs/python/doc/v2/operators.html @@ -0,0 +1,921 @@ + + + + + + + + + + + + Boost.Python - <boost/python/operators.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/operators.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class + self_ns::self_t
+ +
+
+
Class self_t + synopsis
+ +
Class self_t + inplace operators
+ +
Class + self_t comparison functions
+ +
Class self_t + non-member operations
+ +
Class + self_t unary operations
+ +
Class + self_t value operations
+
+
+ +
Class template + other
+ +
+
+
Class other + synopsis
+
+
+ +
Class template + operator_
+ +
+
+
Class + operator_ synopsis
+
+
+
+
+ +
Objects
+ +
+
+
self
+
+
+ +
Examples
+
+
+ +

Introduction

+ +

<boost/python/operators.hpp> provides types and + functions for automatically generating Python special methods + from the corresponding C++ constructs. Most of these constructs are + operator expressions, hence the name. To use the facility, substitute the + self object for an object of the + class type being wrapped in the expression to be exposed, and pass the + result to class_<>::def(). Much of + what is exposed in this header should be considered part of the + implementation, so is not documented in detail here.

+ +

Classes

+ +

Class self_ns::self_t

+ +

self_ns::self_t is the actual type of the self object. The library isolates + self_t in its own namespace, self_ns, in order + to prevent the generalized operator templates which operate on it from + being found by argument-dependent lookup in other contexts. This should + be considered an implementation detail, since users should never have to + mention self_t directly.

+ +

Class self_ns::self_t + synopsis

+
+namespace boost { namespace python { namespace self_ns {
+{
+   unspecified-type-declaration self_t;
+
+   // inplace operators
+   template <class T> operator_<unspecified> operator+=(self_t, T);
+   template <class T> operator_<unspecified> operator-=(self_t, T);
+   template <class T> operator_<unspecified> operator*=(self_t, T);
+   template <class T> operator_<unspecified> operator/=(self_t, T);
+   template <class T> operator_<unspecified> operator%=(self_t, T);
+   template <class T> operator_<unspecified> operator>>=(self_t, T);
+   template <class T> operator_<unspecified> operator<<=(self_t, T);
+   template <class T> operator_<unspecified> operator&=(self_t, T);
+   template <class T> operator_<unspecified> operator^=(self_t, T);
+   template <class T> operator_<unspecified> operator|=(self_t, T);
+
+   // comparisons
+   template <class L, class R> operator_<unspecified> operator==(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator!=(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator<(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator>(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator<=(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator>=(L const&, R const&);
+
+   // non-member operations
+   template <class L, class R> operator_<unspecified> operator+(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator-(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator*(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator/(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator%(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator>>(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator<<(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator&(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator^(L const&, R const&);
+   template <class L, class R> operator_<unspecified> operator|(L const&, R const&);
+   template <class L, class R> operator_<unspecified> pow(L const&, R const&);
+
+   // unary operations
+   operator_<unspecified> operator-(self_t);
+   operator_<unspecified> operator+(self_t);
+   operator_<unspecified> operator~(self_t);
+   operator_<unspecified> operator!(self_t);
+
+   // value operations
+   operator_<unspecified> int_(self_t);
+   operator_<unspecified> long_(self_t);
+   operator_<unspecified> float_(self_t);
+   operator_<unspecified> complex_(self_t);
+   operator_<unspecified> str(self_t);
+
+   operator_<unspecified> repr(self_t);
+
+}}};
+
+ The tables below describe the methods generated when the results of the + expressions described are passed as arguments to class_<>::def(). + x is an object of the class type being wrapped. + +

Class self_t inplace + operators

+ In the table below, If r is an object of type + other<T>, + y is an object of type T; otherwise, + y is an object of the same type as + r. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C++ ExpressionPython Method NameC++ Implementation
self += r__iadd__x += y
self -= r__isub__x -= y
self *= r__imul__x *= y
self /= r__idiv__x /= y
self %= r__imod__x %= y
self >>= r__irshift__x >>= y
self <<= r__ilshift__x <<= y
self &= r__iand__x &= y
self ^= r__ixor__x ^= y
self |= r__ior__x |= y
+ +

Class self_t + comparison functions

+ In the tables below, if r is of type self_t, y is an object of + the same type as x;
+ if l or r is an object of type + other<T>, + y is an object of type T;
+ otherwise, y is an object of the same type as + l or r.
+ l is never of type self_t. + +

The column of Python Expressions illustrates the expressions + that will be supported in Python for objects convertible to the types of + x and y. The secondary operation arises due to + Python's reflection + rules for rich comparison operators, and are only used when the + corresponding operation is not defined as a method of the y + object.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C++ ExpressionPython Method NameC++ ImplementationPython Expressions
+ (primary, secondary)
self == r__eq__x == yx == y, y == x
l == self__eq__y == xy == x, x == y
self != r__ne__x != yx != y, y != x
l != self__ne__y != xy != x, x != y
self < r__lt__x < yx < y, y > x
l < self__gt__y < xy > x, x < y
self > r__gt__x > yx > y, y < x
l > self__lt__y > xy < x, x > y
self <= r__le__x <= yx <= y, y >= x
l <= self__ge__y <= xy >= x, x <= y
self >= r__ge__x >= yx >= y, y <= x
l >= self__le__y >= xy <= x, x >= y
+ +

Class self_t non-member + operations

+ The operations whose names begin with "__r" below will only + be called if the left-hand operand does not already support the given + operation, as described here. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C++ ExpressionPython Method NameC++ Implementation
self + r__add__x + y
l + self__radd__y + x
self - r__sub__x - y
l - self__rsub__y - x
self * r__mul__x * y
l * self__rmul__y * x
self / r__div__x / y
l / self__rdiv__y / x
self % r__mod__x % y
l % self__rmod__y % x
self >> r__rshift__x >> y
l >> self__rrshift__y >> x
self << r__lshift__x << y
l << self__rlshift__y << x
self & r__and__x & y
l & self__rand__y & x
self ^ r__xor__x ^ y
l ^ self__rxor__y ^ x
self | r__or__x | y
l | self__ror__y | x
pow(self, r)__pow__pow(x, y)
pow(l, self)__rpow__pow(y, x)
+ +

Class self_t unary + operations

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C++ ExpressionPython Method NameC++ Implementation
-self__neg__-x
+self__pos__+x
~self__invert__~x
not self
or
!self
__nonzero__!!x
+ +

Class self_t value + operations

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C++ ExpressionPython Method NameC++ Implementation
int_(self)__int__long(x)
long___long__PyLong_FromLong(x)
float___float__double(x)
complex___complex__std::complex<double>(x)
str__str__lexical_cast<std::string>(x)
repr__repr__lexical_cast<std::string>(x)
+ +

Class Template other

+ +

Instances of other<T> can be used in operator + expressions with self; the result is equivalent + to the same expression with a T object in place of + other<T>. Use other<T> to prevent + construction of a T object in case it is heavyweight, when + no constructor is available, or simply for clarity.

+ +

Class Template other synopsis

+
+namespace boost { namespace python
+{
+  template <class T>
+  struct other
+  {
+  };
+}}
+
+ + +

Class Template + detail::operator_

+ +

Instantiations of detail::operator_<> are used as + the return type of operator expressions involving self. This should be considered an implementation + detail and is only documented here as a way of showing how the result of + self-expressions match calls to class_<>::def().

+ +

Class Template + detail::operator_ synopsis

+
+namespace boost { namespace python { namespace detail
+{
+  template <unspecified>
+  struct operator_
+  {
+  };
+}}}
+
+ +

Objects

+ +

self

+
+namespace boost { namespace python
+{
+  using self_ns::self;
+}}
+
+ +

Example

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/operators.hpp>
+#include <boost/operators.hpp>
+
+struct number
+   : boost::integer_arithmetic<number>
+{
+    explicit number(long x_) : x(x_) {}
+    operator long() const { return x; }
+
+    template <class T>
+    number& operator+=(T const& rhs)
+    { x += rhs; return *this; }
+
+    template <class T>
+    number& operator-=(T const& rhs)
+    { x -= rhs; return *this; }
+    
+    template <class T>
+    number& operator*=(T const& rhs)
+    { x *= rhs; return *this; }
+    
+    template <class T>
+    number& operator/=(T const& rhs)
+    { x /= rhs; return *this; }
+    
+    template <class T>
+    number& operator%=(T const& rhs)
+    { x %= rhs; return *this; }
+
+   long x;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(demo)
+{
+   class_<number>("number", init<long>())
+      // interoperate with self
+      .def(self += self)
+      .def(self + self)
+      .def(self -= self)
+      .def(self - self)
+      .def(self *= self)
+      .def(self * self)
+      .def(self /= self)
+      .def(self / self)
+      .def(self %= self)
+      .def(self % self)
+
+      // Convert to Python int
+      .def(int_(self))
+
+      // interoperate with long
+      .def(self += long())
+      .def(self + long())
+      .def(long() + self)
+      .def(self -= long())
+      .def(self - long())
+      .def(long() - self)
+      .def(self *= long())
+      .def(self * long())
+      .def(long() * self)
+      .def(self /= long())
+      .def(self / long())
+      .def(long() / self)
+      .def(self %= long())
+      .def(self % long())
+      .def(long() % self)
+      ;
+}
+
+ +

Revised + + 5 October, 2004 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/overloads.html b/libs/python/doc/v2/overloads.html new file mode 100644 index 0000000000..783e8e5db1 --- /dev/null +++ b/libs/python/doc/v2/overloads.html @@ -0,0 +1,229 @@ + + + + + + + + + + + + Boost.Python - <boost/python/overloads.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/overloads.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
overload-dispatch-expressions
+ +
OverloadDispatcher concept
+ +
Macros
+ +
+
+
BOOST_PYTHON_FUNCTION_OVERLOADS
+ +
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

Defines facilities for generating families of overloaded Python + functions and extension class methods from C++ functions and + member functions with default arguments, or from similar families + of C++ overloads

+ +

overload-dispatch-expressions

+ +

+ An overload-dispatch-expression is used to describe a + family of overloaded methods to be generated for an extension + class. It has the following properties: + +

+
+
docstring: An ntbs + whose value will bound to the methods' __doc__ + attribute
+ +
keywords: A keyword-expression which + will be used to name (a trailing subsequence of) the arguments + to the generated methods.
+ +
call policies: An instance of some type which models CallPolicies.
+ +
minimum arity + The minimum number of arguments to be accepted by a generated + method overload.
+ +
maximum arity + The maximum number of arguments to be accepted by a generated + method overload.
+
+
+ +

OverloadDispatcher Concept

+ + An OverloadDispatcher X is a class which has a + minimum arity and a maximum arity, and for which + the following following are valid overload-dispatch-expressions, + with the same minimum and maximum arity as the OverloadDispatcher. + +
+X()
+X(docstring)
+X(docstring, keywords)
+X(keywords, docstring)
+X()[policies]
+X(docstring)[policies]
+X(docstring, keywords)[policies]
+X(keywords, docstring)[policies]
+
+ +
    +
  • If policies are supplied, it must be an instance of a +type which models CallPolicies, and +will be used as the result's call policies. Otherwise the result's +call policies will be an instance of default_call_policies. + +
  • If docstring is supplied it must be an ntbs, and will be used as the result's docstring. Otherwise the result has an empty docstring. + +
  • If keywords is supplied it must be the result of a keyword-expression + whose length is no greater than X's maximum + arity, and will be used as the result's keywords. Otherwise + the result's keywords will be empty. +
+ + + + +

Macros

+ +

BOOST_PYTHON_FUNCTION_OVERLOADS(name, func_id, min_args, max_args)

+ Expands to the definition of an OverloadDispatcher called + name in the current scope which can be used to + generate the following function invocation: +
+func_id(a1, a2,...ai);
+
+ + for all min_args <= i <= max_args. + +

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(name, member_name, min_args, max_args)

+ + Expands to the definition of an OverloadDispatcher called + name in the current scope which can be used to + generate the following function invocation: +
+x.member_name(a1, a2,...ai);
+
+ + for all min_args <= i <= + max_args, where x is a reference to an + object of class type. + +

Example(s)

+ +
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/args.hpp>
+#include <boost/python/tuple.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/overloads.hpp>
+#include <boost/python/return_internal_reference.hpp>
+
+using namespace boost::python;
+
+tuple f(int x = 1, double y = 4.25, char const* z = "wow")
+{
+    return make_tuple(x, y, z);
+}
+
+BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
+
+struct Y {};
+struct X
+{
+    Y& f(int x, double y = 4.25, char const* z = "wow")
+    {
+        return inner;
+    }
+    Y inner;
+};
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(f_member_overloads, f, 1, 3)
+
+BOOST_PYTHON_MODULE(args_ext)
+{
+    def("f", f, 
+        f_overloads(
+            args("x", "y", "z"), "This is f's docstring"
+        ));
+
+    
+    class_<Y>("Y")
+        ;
+            
+    class_<X>("X", "This is X's docstring")
+        .def("f1", &X::f, 
+                f_member_overloads(
+                    args("x", "y", "z"), "f's docstring"
+                )[return_internal_reference<>()]
+        )
+        ;
+}
+
+ +

Revised + + 15 April, 2003 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/pickle.html b/libs/python/doc/v2/pickle.html new file mode 100644 index 0000000000..22e198d63b --- /dev/null +++ b/libs/python/doc/v2/pickle.html @@ -0,0 +1,280 @@ + + + + + Boost.Python Pickle Support + + + +
+ boost.png (6897 bytes) +
+ +

Boost.Python Pickle Support

Pickle is a Python module for object + serialization, also known as persistence, marshalling, or flattening. + +

It is often necessary to save and restore the contents of an object to + a file. One approach to this problem is to write a pair of functions that + read and write data from a file in a special format. A powerful + alternative approach is to use Python's pickle module. Exploiting + Python's ability for introspection, the pickle module recursively + converts nearly arbitrary Python objects into a stream of bytes that can + be written to a file.

+ +

The Boost Python Library supports the pickle module through the + interface as described in detail in the Python Library + Reference for pickle. This interface involves the special methods + __getinitargs__, __getstate__ and __setstate__ + as described in the following. Note that Boost.Python is also fully + compatible with Python's cPickle module.

+
+ +

The Boost.Python Pickle Interface

At the user level, the + Boost.Python pickle interface involves three special methods: + +
+
__getinitargs__
+ +
+ When an instance of a Boost.Python extension class is pickled, the + pickler tests if the instance has a __getinitargs__ method. + This method must return a Python tuple (it is most convenient to use + a boost::python::tuple). When the instance is restored by the + unpickler, the contents of this tuple are used as the arguments for + the class constructor. + +

If __getinitargs__ is not defined, pickle.load + will call the constructor (__init__) without arguments; + i.e., the object must be default-constructible.

+
+ +
__getstate__
+ +
When an instance of a Boost.Python extension class is pickled, the + pickler tests if the instance has a __getstate__ method. This + method should return a Python object representing the state of the + instance.
+ +
__setstate__
+ +
When an instance of a Boost.Python extension class is restored by + the unpickler (pickle.load), it is first constructed using the + result of __getinitargs__ as arguments (see above). + Subsequently the unpickler tests if the new instance has a + __setstate__ method. If so, this method is called with the + result of __getstate__ (a Python object) as the argument.
+
The three special methods described above may be .def()'ed + individually by the user. However, Boost.Python provides an easy to use + high-level interface via the + boost::python::pickle_suite class that also + enforces consistency: __getstate__ and __setstate__ + must be defined as pairs. Use of this interface is demonstrated by the + following examples. +
+ +

Examples

There are three files in boost/libs/python/test + that show how to provide pickle support. +
+ +

pickle1.cpp

The C++ + class in this example can be fully restored by passing the appropriate + argument to the constructor. Therefore it is sufficient to define the + pickle interface method __getinitargs__. This is done in the + following way: + +
    +
  • 1. Definition of the C++ pickle function: +
    +  struct world_pickle_suite : boost::python::pickle_suite
    +  {
    +    static
    +    boost::python::tuple
    +    getinitargs(world const& w)
    +    {
    +        return boost::python::make_tuple(w.get_country());
    +    }
    +  };
    +
    +
  • + +
  • 2. Establishing the Python binding: +
    +  class_<world>("world", args<const std::string&>())
    +      // ...
    +      .def_pickle(world_pickle_suite())
    +      // ...
    +
    +
  • +
+
+ +

pickle2.cpp

The C++ + class in this example contains member data that cannot be restored by any + of the constructors. Therefore it is necessary to provide the + __getstate__/__setstate__ pair of pickle interface + methods: + +
    +
  • 1. Definition of the C++ pickle functions: +
    +  struct world_pickle_suite : boost::python::pickle_suite
    +  {
    +    static
    +    boost::python::tuple
    +    getinitargs(const world& w)
    +    {
    +      // ...
    +    }
    +
    +    static
    +    boost::python::tuple
    +    getstate(const world& w)
    +    {
    +      // ...
    +    }
    +
    +    static
    +    void
    +    setstate(world& w, boost::python::tuple state)
    +    {
    +      // ...
    +    }
    +  };
    +
    +
  • + +
  • 2. Establishing the Python bindings for the entire suite: +
    +  class_<world>("world", args<const std::string&>())
    +      // ...
    +      .def_pickle(world_pickle_suite())
    +      // ...
    +
    +
  • +
+ +

For simplicity, the __dict__ is not included in the result of + __getstate__. This is not generally recommended, but a valid + approach if it is anticipated that the object's __dict__ will + always be empty. Note that the safety guard described below will catch + the cases where this assumption is violated.

+
+ +

pickle3.cpp

This + example is similar to pickle2.cpp. However, the object's + __dict__ is included in the result of __getstate__. + This requires a little more code but is unavoidable if the object's + __dict__ is not always empty. +
+ +

Pitfall and Safety Guard

The pickle protocol described above has + an important pitfall that the end user of a Boost.Python extension module + might not be aware of: + +

__getstate__ is defined and the instance's + __dict__ is not empty.

+ +

The author of a Boost.Python extension class might provide a + __getstate__ method without considering the possibilities + that:

+ +
    +
  • his class is used in Python as a base class. Most likely the + __dict__ of instances of the derived class needs to be pickled + in order to restore the instances correctly.
  • + +
  • the user adds items to the instance's __dict__ directly. + Again, the __dict__ of the instance then needs to be + pickled.
  • +
+ +

To alert the user to this highly unobvious problem, a safety guard is + provided. If __getstate__ is defined and the instance's + __dict__ is not empty, Boost.Python tests if the class has an + attribute __getstate_manages_dict__. An exception is raised if + this attribute is not defined:

+
+    RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
+
To resolve this problem, it should first be established that the + __getstate__ and __setstate__ methods manage the + instances's __dict__ correctly. Note that this can be done + either at the C++ or the Python level. Finally, the safety guard should + intentionally be overridden. E.g. in C++ (from pickle3.cpp): +
+  struct world_pickle_suite : boost::python::pickle_suite
+  {
+    // ...
+
+    static bool getstate_manages_dict() { return true; }
+  };
+
Alternatively in Python: +
+    import your_bpl_module
+    class your_class(your_bpl_module.your_class):
+      __getstate_manages_dict__ = 1
+      def __getstate__(self):
+        # your code here
+      def __setstate__(self, state):
+        # your code here
+
+
+ +

Practical Advice

+ +
    +
  • In Boost.Python extension modules with many extension classes, + providing complete pickle support for all classes would be a + significant overhead. In general complete pickle support should only be + implemented for extension classes that will eventually be pickled.
  • + +
  • Avoid using __getstate__ if the instance can also be + reconstructed by way of __getinitargs__. This automatically + avoids the pitfall described above.
  • + +
  • If __getstate__ is required, include the instance's + __dict__ in the Python object that is returned.
  • +
+
+ +

Light-weight alternative: pickle support implemented in Python

+ +

pickle4.cpp

The + pickle4.cpp example demonstrates an alternative technique for + implementing pickle support. First we direct Boost.Python via the + class_::enable_pickling() member function to define only the + basic attributes required for pickling: +
+  class_<world>("world", args<const std::string&>())
+      // ...
+      .enable_pickling()
+      // ...
+
This enables the standard Python pickle interface as described in the +Python documentation. By "injecting" a __getinitargs__ method into +the definition of the wrapped class we make all instances pickleable: +
+  # import the wrapped world class
+  from pickle4_ext import world
+
+  # definition of __getinitargs__
+  def world_getinitargs(self):
+    return (self.get_country(),)
+
+  # now inject __getinitargs__ (Python is a dynamic language!)
+  world.__getinitargs__ = world_getinitargs
+
See also the + tutorial section on injecting additional methods from Python. +
+ © Copyright Ralf W. Grosse-Kunstleve 2001-2004. 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) + +

Updated: Feb 2004.

+
+ + diff --git a/libs/python/doc/v2/platforms.html b/libs/python/doc/v2/platforms.html new file mode 100644 index 0000000000..ac984b43fc --- /dev/null +++ b/libs/python/doc/v2/platforms.html @@ -0,0 +1,135 @@ + + + + + + + + + + + + Boost.Python - Known Working Platforms and Compilers + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Known Working Platforms and Compilers

+
+
+ Please see + our regression + logs for up-to-date information. Note that logs not marked + otherwise reflect the CVS state, not the condition of the release. + +

+ Earlier versions of Boost.Python have been successfully + tested on the following platforms and compilers. + +

+
Unix Platforms:
+ +
+
+
with Python 2.2 and 2.2.2b1:
+ +
+
+
GCC 2.95.3, 2.96, 3.0.4, + 3.1, and 3.2 on RedHat Linux 7.3 + for Intel x86
+ +
Tru64 CXX 6.5.1 on OSF v. 5.1 for Dec/Compaq + Alpha
+ +
+ MIPSPro 7.3.1.2m on IRIX 6.5 for SGI + mips
+ +
GCC 3.1 on SunOS 5.8
+
+
+ +
with Python 2.2.1
+ +
+
+
KCC 3.4d on OSF v. 5.1 for Dec/Compaq Alpha
+ +
KCC 3.4d on AIX
+
+
+
+
+
+ +
Microsoft Windows XP Professional with Python 2.2, 2.2.1, and 2.2.2b1:
+ +
+
+
Microsoft Visual + C++ 6, 7, and 7.1 beta
+ +
Microsoft Visual + C++ 6 with STLPort + 4.5.3
+ +
+ Metrowerks CodeWarrior 7.2, 8.0, 8.2 and 8.3 beta
+ +
Intel + C++ 5.0, 6.0, and 7.0 beta
+ +
Intel C++ + 5.0 with STLPort + 4.5.3
+ +
Cygwin GCC 3.0.4 and 3.2
+ +
MinGW-1.1 (GCC 2.95.3-5)
+ +
MinGW-2.0 (GCC 3.2)
+
+
+
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/pointee.html b/libs/python/doc/v2/pointee.html new file mode 100644 index 0000000000..2dcec8c368 --- /dev/null +++ b/libs/python/doc/v2/pointee.html @@ -0,0 +1,119 @@ + + + + + + Boost.Python - <boost/python/pointee.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header <boost/python/pointee.hpp>

+
+
+ +

Contents

+ +
+
Introduction + +
Classes + +
+
+
Class Templatepointee + +
+
+
Class Template + pointee synopsis +
+
+ +
Example +
+
+ +

Introduction

+ +

<boost/python/pointee.hpp> introduces a + traits metafunction + template pointee<T> that can be used to extract the "pointed-to" type from the type of a pointer or smart pointer. + +

Classes

+ +

Class Template pointee<class T>

+ +

pointee<T> is used by the class_<...> + template to deduce the type being held when a pointer or smart + pointer type is used as its HeldType argument. + +

Class Template + pointee synopsis

+
+namespace boost { namespace python
+{
+   template <class T> struct pointee
+   {
+      typedef T::element_type type;
+   };
+
+   // specialization for pointers
+   template <T> struct pointee<T*>
+   {
+      typedef T type;
+   };
+}
+
+ + +

Example

+ +Given a 3rd-party smart pointer type +smart_pointer<T>, one might partially specialize +pointee<smart_pointer<T> > so that it can be +used as the HeldType for a class wrapper: + +
+#include <boost/python/pointee.hpp>
+#include <boost/python/class.hpp>
+#include <third_party_lib.hpp>
+
+namespace boost { namespace python
+{
+  template <class T> struct pointee<smart_pointer<T> >
+  {
+     typedef T type;
+  };
+}}
+
+BOOST_PYTHON_MODULE(pointee_demo)
+{
+   class_<third_party_class, smart_pointer<third_party_class> >("third_party_class")
+      .def(...)
+      ...
+      ;
+}
+
+ +

Revised + + 13 November, 2002 + + + +

© Copyright Dave + Abrahams 2002. 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)

+ + diff --git a/libs/python/doc/v2/progress_reports.html b/libs/python/doc/v2/progress_reports.html new file mode 100644 index 0000000000..5a8b015a20 --- /dev/null +++ b/libs/python/doc/v2/progress_reports.html @@ -0,0 +1,47 @@ + + + + + + + +Boost.Python - Progress Reports + + + + + + + +
+

+

+
+

Boost.Python

+

Progress Reports

+
+
+ +Monthly progress reports are required as part of Boost Consulting's +contract with LLNL for Boost.Python development. These reports contain +a useful record of the project history, including the rationale for +design decisions and links to relevant discussions. + +
+
February 2002
+
March 2002
+
April 2002
+
May 2002
+
June 2002
+
+
+

Revised + + 13 November, 2002 + +

+

© Copyright Dave Abrahams + 2002.

+ + diff --git a/libs/python/doc/v2/ptr.html b/libs/python/doc/v2/ptr.html new file mode 100644 index 0000000000..4aca539158 --- /dev/null +++ b/libs/python/doc/v2/ptr.html @@ -0,0 +1,265 @@ + + + + + + Boost.Python - <boost/python/ptr.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header <boost/python/ptr.hpp>

+
+
+ +

Contents

+ +
+
Introduction + +
Functions +
+
+
ptr +
+ +
Classes +
+
+
Class template pointer_wrapper + +
+
+
Class template pointer_wrapper synopsis + +
Class + pointer_wrapper types + +
Class + pointer_wrapper constructors and destructor + +
Class + pointer_wrapper observer functions + +
+
+ +
Metafunctions +
+
+
Class template is_pointer_wrapper + +
+
+
Class template is_pointer_wrapper synopsis +
+ + +
Class template unwrap_pointer + +
+
+
Class template unwrap_pointer synopsis +
+ +
+ + +
Example(s) +
+
+ +

Introduction

+ +

<boost/python/ptr.hpp> defines the + ptr() function template, which allows users to + specify how to convert C++ pointer values to python in the context + of implementing overridable virtual functions, invoking Python + callable objects, or explicitly converting C++ objects to + Python. Normally, when passing pointers to Python callbacks, the + pointee is copied to ensure that the Python object + never holds a dangling reference. To specify that the new Python + object should merely contain a copy of a pointer p, + the user can pass ptr(p) instead of passing + p directly. This interface is meant to mirror the use + of boost::ref(), + which can be similarly used to prevent copying of referents. + +

ptr(p) returns an instance of pointer_wrapper<>, which + can be detected using the is_pointer_wrapper<> + metafunction; unwrap_pointer<> is a + metafunction which extracts the original pointer type from a + pointer_wrapper<>. These classes can be thought + of as implementation details. + +

Functions

+
+
+template <class T>
+pointer_wrapper<T> ptr(T x);
+
+ +
+
Requires: T is a pointer type. + +
Returns: pointer_wrapper<T>(x) + +
Throws: nothing. +
+ +

Classes

+ +

Class template pointer_wrapper

+ +

A "type envelope" which is returned by ptr(), used to indicate reference semantics + for pointers passed to Python callbacks. + +

Class + pointer_wrapper synopsis

+
+namespace boost { namespace python
+{
+    template<class Ptr> class pointer_wrapper
+    { 
+     public:
+        typedef Ptr type;
+
+        explicit pointer_wrapper(Ptr x);
+        operator Ptr() const;
+        Ptr get() const;
+    };
+}}
+
+ +

Class template pointer_wrapper types

+
+typedef Ptr type;
+
+The type of the pointer being wrapped. + +

Class template pointer_wrapper constructors and + destructor

+
+explicit pointer_wrapper(Ptr x);
+
+ +
+
Requires: Ptr is a pointer type. + +
Effects: Stores x in a the pointer_wrapper<>. +
Throws: nothing. +
+ +

Class template pointer_wrapper observer + functions

+
+operator Ptr() const;
+Ptr get() const;
+
+ +
+
Returns: a copy of the stored pointer. +
Rationale: pointer_wrapper is intended + to be a stand-in for the actual pointer type, but sometimes it's + better to have an explicit way to retrieve the pointer. +
+ +

Metafunctions

+ +

Class template is_pointer_wrapper

+ +

A unary metafunction whose value is true iff its + argument is a pointer_wrapper<>. + +

Class template is_pointer_wrapper synopsis

+
+namespace boost { namespace python
+{
+    template<class T> class is_pointer_wrapper
+    { 
+        static unspecified value = ...;
+    };
+}}
+
+ + +
+
Returns: true iff T is a + specialization of +pointer_wrapper<>. +
value is an integral constant convertible to bool of +unspecified type + +
+ +

Class template unwrap_pointer

+ +A unary metafunction which extracts the wrapped pointer type from a +specialization of pointer_wrapper<>. + +

Class template unwrap_pointer synopsis

+
+namespace boost { namespace python
+{
+    template<class T> class unwrap_pointer
+    { 
+        typedef unspecified type;
+    };
+}}
+
+ +
+
Returns: T::type if T is a + specialization of +pointer_wrapper<>, T otherwise +
+ + +

Example(s)

+ +This example illustrates the use of ptr() to prevent an +object from being copied: +
+#include <boost/python/call.hpp>
+#include <boost/python/ptr.hpp>
+
+class expensive_to_copy
+{
+   ...
+};
+
+void pass_as_arg(expensive_to_copy* x, PyObject* f)
+{
+   // call the Python function f, passing a Python object built around
+   // which refers to *x by-pointer.
+   //
+   // *** Note: ensuring that *x outlives the argument to f() is    ***
+   // *** up to the user! Failure to do so could result in a crash! ***
+
+   boost::python::call<void>(f, ptr(x));
+}
+...
+
+ +

Revised + + 13 November, 2002 + + + +

© Copyright Dave + Abrahams 2002. 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)

+ diff --git a/libs/python/doc/v2/python.html b/libs/python/doc/v2/python.html new file mode 100644 index 0000000000..9c4e27ec63 --- /dev/null +++ b/libs/python/doc/v2/python.html @@ -0,0 +1,110 @@ + + + + + + + + + + + + Boost.Python - <boost/python.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+
+
+ +

Introduction

+ +

This is a convenience header which #includes all of the public + interface headers that are part of the Boost.Python library

+
+# include <args.hpp>
+# include <args_fwd.hpp>
+# include <back_reference.hpp>
+# include <bases.hpp>
+# include <borrowed.hpp>
+# include <call.hpp>
+# include <call_method.hpp>
+# include <class.hpp>
+# include <copy_const_reference.hpp>
+# include <copy_non_const_reference.hpp>
+# include <data_members.hpp>
+# include <def.hpp>
+# include <default_call_policies.hpp>
+# include <dict.hpp>
+# include <enum.hpp>
+# include <errors.hpp>
+# include <exception_translator.hpp>
+# include <extract.hpp>
+# include <handle.hpp>
+# include <has_back_reference.hpp>
+# include <implicit.hpp>
+# include <init.hpp>
+# include <instance_holder.hpp>
+# include <iterator.hpp>
+# include <list.hpp>
+# include <long.hpp>
+# include <lvalue_from_pytype.hpp>
+# include <make_function.hpp>
+# include <manage_new_object.hpp>
+# include <module.hpp>
+# include <numeric.hpp>
+# include <object.hpp>
+# include <object_protocol.hpp>
+# include <object_protocol_core.hpp>
+# include <operators.hpp>
+# include <other.hpp>
+# include <overloads.hpp>
+# include <pointee.hpp>
+# include <ptr.hpp>
+# include <reference_existing_object.hpp>
+# include <return_internal_reference.hpp>
+# include <return_value_policy.hpp>
+# include <scope.hpp>
+# include <self.hpp>
+# include <slice_nil.hpp>
+# include <str.hpp>
+# include <to_python_converter.hpp>
+# include <to_python_indirect.hpp>
+# include <to_python_value.hpp>
+# include <tuple.hpp>
+# include <type_id.hpp>
+# include <with_custodian_and_ward.hpp>
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/pytype_function.html b/libs/python/doc/v2/pytype_function.html new file mode 100644 index 0000000000..fcc2a7f928 --- /dev/null +++ b/libs/python/doc/v2/pytype_function.html @@ -0,0 +1,370 @@ + + + + + + + + + + + Boost.Python - + <boost/python/doobject/pytype_function.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/converter/pytype_function.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class + wrap_pytype
+ +
+
+
Class + wrap_pytype synopsis
+ +
+
+
+
+ +
+
+
Class + registered_pytype
+ +
+
+
Class + registered_pytype synopsis
+ +
+
+
+
+ +
+
+
Class + expected_from_python_type
+ +
+
+
Class + expected_from_python_type synopsis
+ +
+
+
+
+ +
+
+
Class + to_python_target_type
+ +
+
+
Class + to_python_target_type synopsis
+ +
+
+
+
+ +
Examples
+
+
+ +

Introduction

+ +

To support Pythonic signatures the converters should supply a get_pytype function + returning a pointer to the associated PyTypeObject. See for example + ResultConverter or + to_python_converter. + The classes in this header file are meant to be used when implmenting get_pytype. + There are also _direct versions of the templates of class T which + should be used with undecorated type parameter, expected to be in the conversion registry when the module loads. +

+ +

Classes

+ +

Class + wrap_pytype

+ +

+ This template generates a static get_pytype member returning the template parameter. +

+ +

Class + wrap_pytype synopsis

+
+namespace boost { namespace python { namespace converter{
+
+    template < PyTypeObject const *pytype >
+    class wrap_pytype 
+    {
+      public:
+          static PyTypeObject const *get_pytype(){return pytype; }
+    };
+
+}}}
+
+ + +

Class + registered_pytype

+ +

+ This template should be used with template parameters which are (possibly decorated) + types exported to python using class_. + The generated a static get_pytype member + returns the corresponding python type. +

+ +

Class + registered_pytype synopsis

+
+namespace boost { namespace python { namespace converter{
+
+    template < class T >
+    class registered_pytype 
+    {
+      public:
+          static PyTypeObject const *get_pytype();
+    };
+
+}}}
+
+ + +

Class + expected_from_python_type

+ +

+ This template generates a static get_pytype member which inspects the registered + from_python converters for the type T and returns a matching python type. +

+ +

Class + expected_from_python_type synopsis

+
+namespace boost { namespace python { namespace converter{
+
+    template < class T >
+    class expected_from_python_type 
+    {
+      public:
+          static PyTypeObject const *get_pytype();
+    };
+
+}}}
+
+ + +

Class + to_python_target_type

+ +

+ This template generates a static get_pytype member returning the + python type to which T can be converted. +

+ +

Class + to_python_target_type synopsis

+
+namespace boost { namespace python { namespace converter{
+
+    template < class T >
+    class to_python_target_type 
+    {
+      public:
+          static PyTypeObject const *get_pytype();
+    };
+
+}}}
+
+ + +

Examples

+ + This example presumes that someone has implemented the standard noddy example + module from the Python documentation, and placed the corresponding + declarations in "noddy.h". Because + noddy_NoddyObject is the ultimate trivial extension type, + the example is a bit contrived: it wraps a function for which all + information is contained in the type of its return value. + +

C++ module definition

+
+#include <boost/python/reference.hpp>
+#include <boost/python/module.hpp>
+#include "noddy.h"
+
+struct tag {};
+tag make_tag() { return tag(); }
+
+using namespace boost::python;
+
+struct tag_to_noddy 
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
+: wrap_pytype<&noddy_NoddyType> //inherits get_pytype from wrap_pytype
+#endif
+{
+    static PyObject* convert(tag const& x)
+    {
+        return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
+    }
+};
+
+BOOST_PYTHON_MODULE(to_python_converter)
+{
+    def("make_tag", make_tag);
+    to_python_converter<tag, tag_to_noddy
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
+          , true
+#endif
+          >(); //"true" because tag_to_noddy has member get_pytype
+}
+
+ + +

The following example registers to and from python converters using the templates +expected_from_python_type and to_pyhton_target_type. +

+
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <boost/python/extract.hpp>
+#include <boost/python/to_python_converter.hpp>
+#include <boost/python/class.hpp>
+
+using namespace boost::python;
+
+struct A
+{
+};
+
+struct B
+{
+  A a;
+  B(const A& a_):a(a_){}
+};
+
+// Converter from A to python int
+struct BToPython 
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
+   : converter::to_python_target_type<A>  //inherits get_pytype
+#endif
+{
+  static PyObject* convert(const B& b)
+  {
+    return incref(object(b.a).ptr());
+  }
+};
+
+// Conversion from python int to A
+struct BFromPython
+{
+  BFromPython()
+  {
+    boost::python::converter::registry::push_back
+        ( &convertible
+        , &construct
+        , type_id< B >()
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
+        , &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B
+#endif
+        );
+  }
+
+  static void* convertible(PyObject* obj_ptr)
+  {
+      extract<const A&> ex(obj_ptr);
+      if (!ex.check()) return 0;
+      return obj_ptr;
+  }
+
+  static void construct(
+      PyObject* obj_ptr,
+      converter::rvalue_from_python_stage1_data* data)
+  {
+    void* storage = (
+        (converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;
+
+    extract<const A&> ex(obj_ptr);
+    new (storage) B(ex());
+    data->convertible = storage;
+  }
+};
+
+
+B func(const B& b) { return b ; }
+
+BOOST_PYTHON_MODULE(pytype_function_ext)
+{
+  to_python_converter< B , BToPython
+#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
+             ,true 
+#endif
+             >(); //has get_pytype
+  BFromPython();
+
+  class_<A>("A") ;
+
+  def("func", &func);
+
+}
+
+
+
+>>> from pytype_function_ext import *
+>>> print func.__doc__
+func( (A)arg1) -> A :
+    C++ signature:
+         struct B func(struct B)
+
+ + +

© Copyright Nikolay Mladenov 2007.

+ + diff --git a/libs/python/doc/v2/raw_function.html b/libs/python/doc/v2/raw_function.html new file mode 100644 index 0000000000..0ad4c37c24 --- /dev/null +++ b/libs/python/doc/v2/raw_function.html @@ -0,0 +1,118 @@ + + + + + + + + + + + + Boost.Python - <boost/python/raw_function.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/raw_function.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Functions
+ +
+
+
raw_function
+
+
+ +
Example
+
+
+ +

Introduction

+ +

raw_function(...) + is used to convert a function taking a tuple and a dict into a Python callable object + which accepts a variable number of arguments and arbitrary keyword + arguments. + +

Functions

+ raw_function +
+template <class F>
+object raw_function(F f, std::size_t min_args = 0);
+
+ +
+
Requires: f(tuple(), dict()) is + well-formed.
+ +
Returns: a callable object which requires at least min_args arguments. When called, the actual non-keyword arguments will be passed in a tuple as the first argument to f, and the keyword arguments will be passed in a dict as the second argument to f. + + +
+ +

Example

+C++: +
+#include <boost/python/def.hpp>
+#include <boost/python/tuple.hpp>
+#include <boost/python/dict.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/raw_function.hpp>
+
+using namespace boost::python;
+
+tuple raw(tuple args, dict kw)
+{
+    return make_tuple(args, kw);
+}
+
+BOOST_PYTHON_MODULE(raw_test)
+{
+    def("raw", raw_function(raw));
+}
+
+ +Python: +
+>>> from raw_test import *
+
+>>> raw(3, 4, foo = 'bar', baz = 42)
+((3, 4), {'foo': 'bar', 'baz': 42})
+
+

+ + 7 March, 2003 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/reference.html b/libs/python/doc/v2/reference.html new file mode 100644 index 0000000000..5ebdad105e --- /dev/null +++ b/libs/python/doc/v2/reference.html @@ -0,0 +1,1192 @@ + + + + + + + + + + + + Boost.Python - Reference + + + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Reference

+
+
+ +

Contents

+ +
+
Concepts
+ +
High Level Components
+ +
Object Wrappers
+ +
Function Invocation and Creation
+ +
+
+
Models of + CallPolicies
+ +
Models of + ResultConverter
+ +
Models of + ResultConverterGenerator
+
+
+ +
To/From Python Type Conversion
+ +
Embedding
+ +
Utility and Infrastructure
+ +
Topics
+
+
+ + +

Concepts

+ +
+
CallPolicies
+ +
Dereferenceable
+ +
Extractor
+ +
HolderGenerator
+ +
ResultConverter
+ +
ResultConverterGenerator
+ +
ObjectWrapper
+ +
TypeWrapper
+
+ +

High Level Components

+ +
+
class.hpp/class_fwd.hpp
+ +
+
+
Classes
+ +
+
+
class_
+ +
bases
+
+
+
+
+ +
def.hpp
+ +
+
+
Functions
+ +
+
+
def
+
+
+
+
+ +
def_visitor.hpp
+ +
+
+
Classes
+
+
+ +
docstring_options.hpp
+ +
+
+
Classes
+
+
+ +
enum.hpp
+ +
+
+
Classes
+ +
+
+
enum_
+
+
+
+
+ +
errors.hpp
+ +
+
+
Classes
+ +
+
+
error_already_set
+
+
+ +
Functions
+ +
+
+
handle_exception
+ +
expect_non_null
+ +
throw_error_already_set
+
+
+
+
+ +
exception_translator.hpp
+ +
+
+
Functions
+ +
+
+
register_exception_translator
+
+
+
+
+ +
init.hpp
+ +
+
+
Classes
+ +
+
+
init
+ +
optional
+
+
+
+
+ +
iterator.hpp
+ +
+
+
Classes
+ +
+
+
iterator
+ +
iterators
+
+
+ +
Functions
+ +
+
+
range
+
+
+
+
+ +
module.hpp
+ +
+
+
Macros
+ +
+
+
BOOST_PYTHON_MODULE
+
+
+
+
+ +
operators.hpp
+ +
+
+
Classes
+ +
+
+
self_t
+ +
other
+ +
operator_
+
+
+ +
Objects
+ +
+
+
self
+
+
+
+
+ +
scope.hpp
+ +
+
+
Classes
+ +
+
+
scope
+
+
+
+
+ +
stl_iterator.hpp
+ +
+
+
Classes
+ +
+
+
stl_input_iterator
+
+
+
+
+ +
wrapper.hpp
+ +
+
+
Classes
+ +
+
+
override
+ +
wrapper
+
+
+
+
+
+ +

Object Wrappers

+ +
+
dict.hpp
+ +
+
+
Classes
+ +
+
+
dict
+
+
+
+
+ +
list.hpp
+ +
+
+
Classes
+ +
+
+
list
+
+
+
+
+ +
long.hpp
+ +
+
+
Classes
+ +
+
+
long_
+
+
+
+
+ +
numeric.hpp
+ +
+
+
Classes
+ +
+
+
numeric::array
+
+
+
+
+ +
object.hpp
+ +
+
+
Classes
+ +
+
+
object
+
+
+
+
+ +
str.hpp
+ +
+
+
Classes
+ +
+
+
str
+
+
+
+
+ +
tuple.hpp
+ +
+
+
Classes
+ +
+
+
tuple
+
+
+ +
Functions
+ +
+
+
make_tuple
+
+
+
+
+ +
slice.hpp
+ +
+
+
Classes
+ +
+
+
slice
+
+
+
+
+
+ +

Function Invocation and Creation

+ +
+
args.hpp
+ +
+
+
Functions
+ +
+
+
args
+
+
+
+
+ +
call.hpp
+ +
+
+
Functions
+ +
+
+
call
+
+
+
+
+ +
call_method.hpp
+ +
+
+
Functions
+ +
+
+
call_method
+
+
+
+
+ +
data_members.hpp
+ +
+
+
Functions
+ +
+
+
make_getter
+ +
make_setter
+
+
+
+
+ +
make_function.hpp
+ +
+
+
Functions
+ +
+
+
make_function
+ +
make_constructor
+
+
+
+
+ +
overloads.hpp
+ +
+
+
macros
+ +
+
+
BOOST_PYTHON_FUNCTION_OVERLOADS
+ +
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
+
+
+
+
+ +
ptr.hpp
+ +
+
+
Functions
+ +
+
+
ptr
+
+
+ +
Classes
+ +
+
+
pointer_wrapper
+
+
+ +
MetaFunctions
+ +
+
+
is_pointer_wrapper
+ +
unwrap_pointer
+
+
+
+
+ +
raw_function.hpp
+ +
+
+
Functions
+ +
+
+
raw_function
+
+
+
+
+ +
+ + +

Function documentation

+ +
+
function_doc_signature.hpp
+ +
+
+
Classes
+ +
+
+
function_doc_signature_generator
+ +
+
+
+
+
+
+
pytype_function.hpp
+ +
+
+
Classes
+ +
+
+
wrap_pytype
+ +
+
+
expected_from_python_type
+ +
+
+
to_python_target_type
+ +
+
+
registered_pytype
+ +
+
+
+
+
+
+ +
+ + +

Models of CallPolicies

+ +
+
default_call_policies.hpp
+ +
+
+
Classes
+ +
+
+
default_call_policies
+ +
default_result_converter
+
+
+
+
+ +
return_arg.hpp
+ +
+
+
Classes
+ +
+
+
return_arg
+ +
return_self
+
+
+
+
+ +
return_internal_reference.hpp
+ +
+
+
Classes
+ +
+
+
+ return_internal_reference
+
+
+
+
+ +
return_value_policy.hpp
+ +
+
+
Classes
+ +
+
+
return_value_policy
+
+
+
+
+ +
with_custodian_and_ward.hpp
+ +
+
+
Classes
+ +
+
+
+ with_custodian_and_ward
+ +
+ with_custodian_and_ward_postcall
+
+
+
+
+
+ + +

Models of ResultConverter

+ +
+
to_python_indirect.hpp
+ +
+
+
Classes
+ +
+
+
to_python_indirect
+
+
+
+
+ +
to_python_value.hpp
+ +
+
+
Classes
+ +
+
+
to_python_value
+
+
+
+
+
+ + +

Models of ResultConverterGenerator

+ +
+
copy_const_reference.hpp
+ +
+
+
Classes
+ +
+
+
copy_const_reference
+
+
+
+
+ +
copy_non_const_reference.hpp
+ +
+
+
Classes
+ +
+
+
+ copy_non_const_reference
+
+
+
+
+ +
manage_new_object.hpp
+ +
+
+
Classes
+ +
+
+
manage_new_object
+
+
+
+
+ +
reference_existing_object.hpp
+ +
+
+
Classes
+ +
+
+
+ reference_existing_object
+
+
+
+
+ +
return_by_value.hpp
+ +
+
+
Classes
+ +
+
+
return_by_value
+
+
+
+
+ +
return_opaque_pointer.hpp
+ +
+
+
Classes
+ +
+
+
return_opaque_pointer
+
+
+
+
+
+
+
+ +

To/From Python Type Conversion

+ +
+
extract.hpp
+ +
+
+
Classes
+ +
+
+
extract
+
+
+
+
+ +
implicit.hpp
+ +
+
+
Functions
+ +
+
+
implicitly_convertible
+
+
+
+
+ +
lvalue_from_pytype.hpp
+ +
+
+
Classes
+ +
+
+
lvalue_from_pytype
+ +
extract_identity
+ +
extract_member
+
+
+
+
+ +
opaque_pointer_converter.hpp
+ +
+
+
Classes
+ +
+
+
opaque
+
+
+ +
Macros
+ +
+
+
+ BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
+
+
+
+
+ +
to_python_converter.hpp
+ +
+
+
Classes
+ +
+
+
to_python_converter
+
+
+
+
+ +
register_ptr_to_python.hpp
+ +
+
+
Functions
+ +
+
+
register_ptr_to_python
+
+
+
+
+
+ +

Embedding

+ +
+
exec.hpp
+ +
+
+
Functions
+ +
+
+
eval
+
exec
+
exec_file
+
+
+
+
+ +
import.hpp
+ +
+
+
Functions
+ +
+
+
import
+
+
+
+
+
+ +

Utility and Infrastructure

+ +
+
has_back_reference.hpp
+ +
+
+
Classes
+ +
+
+
has_back_reference
+
+
+
+
+ +
instance_holder.hpp
+ +
+
+
Classes
+ +
+
+
instance_holder
+
+
+
+
+ +
pointee.hpp
+ +
+
+
Classes
+ +
+
+
class template pointee
+
+
+
+
+ +
<boost/python.hpp>
+ +
handle.hpp
+ +
+
+
Classes
+ +
+
+
handle
+
+
+ +
Functions
+ +
+
+
borrowed
+ +
allow_null
+
+
+
+
+ +
type_id.hpp
+ +
+
+
Functions
+ +
+
+
type_id
+
+
+ +
Classes
+ +
+
+
type_info
+
+
+
+
+ +
ssize_t.hpp
+ +
+
+
Typedefs
+ +
Constants
+
+
+
+ +

Topics

+ +
+
Calling Python Functions and + Methods
+ +
Pickle Support
+ Indexing Support
+
+
+ +

Revised + + 31 October, 2004 + +

+ +

© Copyright Dave Abrahams 2002 +.

+ + + diff --git a/libs/python/doc/v2/reference_existing_object.html b/libs/python/doc/v2/reference_existing_object.html new file mode 100644 index 0000000000..12e228f50e --- /dev/null +++ b/libs/python/doc/v2/reference_existing_object.html @@ -0,0 +1,180 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/reference_existing_object.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/reference_existing_object.hpp>

+
+
+ +

Contents

+ +
+
Classes
+ +
+
+
Class + reference_existing_object
+ +
+
+
Class + reference_existing_object synopsis
+ +
Class + reference_existing_object metafunctions
+
+
+
+
+ +
Example
+
+
+ +

Classes

+ +

Class + reference_existing_object

+ +

reference_existing_object is a model of ResultConverterGenerator + which can be used to wrap C++ functions which return a reference or + pointer to a C++ object. When the wrapped function is called, the value + referenced by its return value is not copied. A new Python object is + created which contains a pointer to the referent, and no attempt is made + to ensure that the lifetime of the referent is at least as long as that + of the corresponding Python object. Thus, it can be highly dangerous to use + reference_existing_object without additional lifetime + management from such models of CallPolicies as with_custodian_and_ward. + This class is used in the implementation of return_internal_reference.

+ +

Class + reference_existing_object synopsis

+
+namespace boost { namespace python
+{
+    struct reference_existing_object
+    {
+        template <class T> struct apply;
+    };
+}}
+
+ +

Class + reference_existing_object metafunctions

+
+template <class T> struct apply
+
+ +
+
Requires: T is U& or + U*for some U.
+ +
Returns: typedef to_python_indirect<T,V> + type, where V is a class whose + static execute function constructs an instance + holder containing an unowned + U* pointing to the referent of the wrapped function's + return value.
+
+ +

Example

+ +

In C++:

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/reference_existing_object.hpp>
+#include <boost/python/return_value_policy.hpp>
+#include <utility>
+
+// classes to wrap
+struct Singleton
+{
+   Singleton() : x(0) {}
+
+   int exchange(int n)  // set x and return the old value
+   {
+        std::swap(n, x);
+        return n;
+   }
+
+   int x;
+};
+
+Singleton& get_it()
+{
+   static Singleton just_one;
+   return just_one;
+}
+
+// Wrapper code
+using namespace boost::python;
+BOOST_PYTHON_MODULE(singleton)
+{
+    def("get_it", get_it,
+        return_value_policy<reference_existing_object>());
+
+    class_<Singleton>("Singleton")
+       .def("exchange", &Singleton::exchange)
+       ;
+}
+
+ In Python: +
+>>> import singleton
+>>> s1 = singleton.get_it()  
+>>> s2 = singleton.get_it()
+>>> id(s1) == id(s2)  # s1 and s2 are not the same object
+0
+>>> s1.exchange(42)   # but they reference the same C++ Singleton
+0
+>>> s2.exchange(99)
+42
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/register_ptr_to_python.html b/libs/python/doc/v2/register_ptr_to_python.html new file mode 100644 index 0000000000..5f660e18f0 --- /dev/null +++ b/libs/python/doc/v2/register_ptr_to_python.html @@ -0,0 +1,162 @@ + + + + + + + +Boost.Python - <register_ptr_to_python.hpp> + + + + + + + +
+

+

+
+

Boost.Python

+

Header <register_ptr_to_python.hpp>

+
+
+

Contents

+
+
Introduction
+
Functions
+
+
register_ptr_to_python
+
+ +
Example(s)
+ +
+
+

Introduction

+

+ <boost/python/register_ptr_to_python.hpp> + supplies register_ptr_to_python, a function template + which registers a conversion for smart pointers to Python. The + resulting Python object holds a copy of the converted smart pointer, + but behaves as though it were a wrapped copy of the pointee. If + the pointee type has virtual functions and the class representing + its dynamic (most-derived) type has been wrapped, the Python object + will be an instance of the wrapper for the most-derived type. More than + one smart pointer type for a pointee's class can be registered. +

+

+ Note that in order to convert a Python X object to a + smart_ptr<X>& (non-const reference), the embedded C++ + object must be held by smart_ptr<X>, and that when wrapped + objects are created by calling the constructor from Python, how they are held + is determined by the HeldType parameter to + class_<...> instances. +

+ +

Functions

+
+template <class P>
+void register_ptr_to_python() 
+
+
+
Requires: P is Dereferenceable. +
+
Effects: Allows conversions to-python of P + instances. +
+
+ +

Example(s)

+ +

C++ Wrapper Code

+ +Here is an example of a module that contains a class A with +virtual functions and some functions that work with +boost::shared_ptr<A>. + +
+struct A
+{
+    virtual int f() { return 0; }
+};
+
+shared_ptr<A> New() { return shared_ptr<A>( new A() ); }
+
+int Ok( const shared_ptr<A>& a ) { return a->f(); }
+
+int Fail( shared_ptr<A>& a ) { return a->f(); }
+
+struct A_Wrapper: A
+{
+    A_Wrapper(PyObject* self_): self(self_) {}
+    int f() { return call_method<int>(self, "f"); }    
+    int default_f() { return A::f(); }    
+    PyObject* self;
+};
+
+BOOST_PYTHON_MODULE(register_ptr)
+{
+    class_<A, A_Wrapper>("A")
+        .def("f", &A::f, &A_Wrapper::default_f)
+    ;
+    
+    def("New", &New);
+    def("Ok", &Call);
+    def("Fail", &Fail);
+    
+    register_ptr_to_python< shared_ptr<A> >();
+} 
+
+ +

Python Code

+ +
+>>> from register_ptr import *
+>>> a = A()
+>>> Ok(a)     # ok, passed as shared_ptr<A>
+0
+>>> Fail(a)   # passed as shared_ptr<A>&, and was created in Python!
+Traceback (most recent call last):
+  File "<stdin>", line 1, in ?
+TypeError: bad argument type for built-in operation
+>>>
+>>> na = New()   # now "na" is actually a shared_ptr<A> 
+>>> Ok(a)
+0
+>>> Fail(a)
+0
+>>>
+
+ +If shared_ptr<A> is registered as follows: + +
+    class_<A, A_Wrapper, shared_ptr<A> >("A")
+        .def("f", &A::f, &A_Wrapper::default_f)
+    ;            
+
+ +There will be an error when trying to convert shared_ptr<A> to +shared_ptr<A_Wrapper>: + +
+>>> a = New()
+Traceback (most recent call last):
+File "<stdin>", line 1, in ?
+TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<struct A>
+>>>    
+
+ +

Revised + + 24 Jun, 2003 + +

+

© Copyright Dave Abrahams + 2002.

+ + + + diff --git a/libs/python/doc/v2/return_arg.html b/libs/python/doc/v2/return_arg.html new file mode 100644 index 0000000000..44cd58c24e --- /dev/null +++ b/libs/python/doc/v2/return_arg.html @@ -0,0 +1,224 @@ + + + + + + + + + + + + Boost.Python - <boost/python/return_arg.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/return_arg.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class Template + return_arg
+ +
+
+
Class Template + return_arg synopsis
+ +
Class + return_arg static functions
+
+
+ +
Class Template + return_self
+
+
+ +
Example
+
+
+ +

Introduction

+ return_arg and return_self instantiations are + models of CallPolicies which return the + specified argument parameter (usually *this) of a wrapped + (member) function. + +

Classes

+ +

Class template + return_arg

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ return_arg template parameters +
ParameterRequirementsDescriptionDefault
arg_posA positive compile-time constant of type + std::size_t.the position of the argument to be returned.1
BaseA model of CallPoliciesUsed for policy composition. Any result_converter it + supplies will be overridden by return_arg, but its + precall and postcall policies are composed + as described here CallPolicies.default_call_policies
+ +

Class template + return_arg synopsis

+
+namespace boost { namespace python
+{
+   template <size_t arg_pos=1, class Base = default_call_policies>
+   struct return_arg : Base
+   {
+      static PyObject* postcall(PyObject*, PyObject* result);
+      struct result_converter{ template <class T> struct apply; };
+      template <class Sig> struct extract_return_type : mpl::at_c<Sig, arg_pos>{};
+
+   };
+}}
+
+ +

Class return_arg + static functions

+
+PyObject* postcall(PyObject* args, PyObject* result);
+
+ +
+
Requires: PyTuple_Check(args) + != 0 and PyTuple_Size(args) != 0
+ +
Returns: PyTuple_GetItem(args,arg_pos-1)
+
+ +

Class template + return_self

+ +

Class template return_self synopsis:

+
+namespace boost { namespace python
+{
+   template <class Base = default_call_policies>
+   struct return_self 
+     : return_arg<1,Base>
+   {};
+}}
+
+ +

Example

+ +

C++ module definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/return_arg.hpp>
+
+struct Widget
+{
+   Widget() :sensitive_(true){}
+   bool get_sensitive() const { return sensitive_; }
+   void set_sensitive(bool s) { this->sensitive_ = s; }
+ private:
+   bool sensitive_;
+};
+
+struct Label : Widget
+{
+   Label() {}
+
+   std::string  get_label() const { return label_; }
+   void set_label(const std::string &l){ label_ = l; }
+
+ private:
+   std::string label_;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(return_self_ext)
+{
+   class_<widget>("Widget")
+      .def("sensitive", &Widget::get_sensitive)
+      .def("sensitive", &Widget::set_sensitive, return_self<>())
+      ;
+
+   class_<Label, bases<Widget> >("Label")
+      .def("label", &Label::get_label)
+      .def("label", &Label::set_label, return_self<>())
+      ;
+}
+
+
+
+ +

Python code

+
+>>> from return_self_ext import *
+>>> l1 = Label().label("foo").sensitive(false)
+>>> l2 = Label().sensitive(false).label("foo") 
+
+ +

Revised + + 19 July, 2003 +

+ +

© Copyright Dave Abrahams and Nikolay + Mladenov 2003.

+ + + diff --git a/libs/python/doc/v2/return_by_value.html b/libs/python/doc/v2/return_by_value.html new file mode 100644 index 0000000000..12ca3c43fd --- /dev/null +++ b/libs/python/doc/v2/return_by_value.html @@ -0,0 +1,149 @@ + + + + + + + + + + + + Boost.Python - <boost/python/return_by_value.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/return_by_value.hpp>

+
+
+ +

Contents

+ +
+
Classes
+ +
+
+
Class + return_by_value
+ +
+
+
Class + return_by_value synopsis
+ +
Class + return_by_value metafunctions
+
+
+
+
+ +
Example
+
+
+ +

Classes

+ +

Class + return_by_value

+ +

return_by_value is a model of ResultConverterGenerator + which can be used to wrap C++ functions returning any reference or value + type such that the return value is copied into a new Python object.

+ +

Class + return_by_value synopsis

+
+namespace boost { namespace python
+{
+    struct return_by_value
+    {
+        template <class T> struct apply;
+    };
+}}
+
+ +

Class + return_by_value metafunctions

+
+template <class T> struct apply
+
+ +
+
Returns: typedef to_python_value<T> + type;
+
+ +

Example

+ +

C++ Module Definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/return_by_value.hpp>
+#include <boost/python/return_value_policy.hpp>
+
+// classes to wrap
+struct Bar { };
+
+Bar global_bar;
+
+// functions to wrap:
+Bar b1();
+Bar& b2();
+Bar const& b3();
+
+// Wrapper code
+using namespace boost::python;
+template <class R>
+void def_void_function(char const* name, R (*f)())
+{
+   def(name, f, return_value_policy<return_by_value>());
+}
+
+BOOST_PYTHON_MODULE(my_module)
+{
+    class_<Bar>("Bar");
+    def_void_function("b1", b1);
+    def_void_function("b2", b2);
+    def_void_function("b3", b3);
+}
+
+ +

Python Code

+
+>>> from my_module import *
+>>> b = b1() # each of these calls
+>>> b = b2() # creates a brand
+>>> b = b3() # new Bar object
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/return_internal_reference.html b/libs/python/doc/v2/return_internal_reference.html new file mode 100644 index 0000000000..87c33f855b --- /dev/null +++ b/libs/python/doc/v2/return_internal_reference.html @@ -0,0 +1,230 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/return_internal_reference.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/return_internal_reference.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class Template + return_internal_reference
+ +
+
+
Class + Template return_internal_reference + synopsis
+ +
Class + return_internal_reference static + functions
+
+
+
+
+ +
Example
+
+
+ +

Introduction

+ return_internal_reference instantiations are models of CallPolicies which allow pointers and + references to objects held internally by a free or member function + argument or from the target of a member function to be returned safely + without making a copy of the referent. The default for its first template + argument handles the common case where the containing object is the + target (*this) of a wrapped member function. + +

Classes

+ +

Class template + return_internal_reference

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ return_internal_reference template parameters +
ParameterRequirementsDescriptionDefault
owner_argA positive compile-time constant of type + std::size_t.The index of the parameter which contains the object to which the + reference or pointer is being returned. If used to wrap a member + function, parameter 1 is the target object (*this). Note + that if the target Python object type doesn't support weak + references, a Python TypeError exception will be raised + when the function being wrapped is called.1
BaseA model of CallPoliciesUsed for policy composition. Any result_converter it + supplies will be overridden by + return_internal_reference, but its precall + and postcall policies are composed as described here CallPolicies.default_call_policies
+ +

Class template + return_internal_reference synopsis

+
+namespace boost { namespace python
+{
+   template <std::size_t owner_arg = 1, class Base = default_call_policies>
+   struct return_internal_reference : Base
+   {
+      static PyObject* postcall(PyObject*, PyObject* result);
+      typedef reference_existing_object result_converter;
+   };
+}}
+
+ +

Class + return_internal_reference static functions

+
+PyObject* postcall(PyObject* args, PyObject* result);
+
+ +
+
Requires: PyTuple_Check(args) + != 0
+ +
Returns: + with_custodian_and_ward_postcall::postcall(args, + result)
+
+ +

Example

+ +

C++ module definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/return_internal_reference.hpp>
+
+class Bar
+{
+ public:
+   Bar(int x) : x(x) {}
+   int get_x() const { return x; }
+   void set_x(int x) { this->x = x; }
+ private:
+   int x;
+};
+
+class Foo
+{
+ public:
+   Foo(int x) : b(x) {}
+
+   // Returns an internal reference
+   Bar const& get_bar() const { return b; }
+
+ private:
+   Bar b;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(internal_refs)
+{
+   class_<Bar>("Bar", init<int>())
+      .def("get_x", &Bar::get_x)
+      .def("set_x", &Bar::set_x)
+      ;
+
+   class_<Foo>("Foo", init<int>())
+      .def("get_bar", &Foo::get_bar
+          , return_internal_reference<>())
+      ;
+}
+
+ +

Python code

+
+>>> from internal_refs import *
+>>> f = Foo(3)
+>>> b1 = f.get_bar()
+>>> b2 = f.get_bar()
+>>> b1.get_x()
+3
+>>> b2.get_x()
+3
+>>> b1.set_x(42)
+>>> b2.get_x()
+42
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/return_opaque_pointer.html b/libs/python/doc/v2/return_opaque_pointer.html new file mode 100644 index 0000000000..52d8396e83 --- /dev/null +++ b/libs/python/doc/v2/return_opaque_pointer.html @@ -0,0 +1,192 @@ + + + + + + + + + + + Boost.Python - <boost/python/return_opaque_pointer.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/return_opaque_pointer.hpp>

+
+
+ +

Contents

+ +
+
Classes
+ +
+
+
Class + return_opaque_pointer
+ +
+
+
Class + return_opaque_pointer synopsis
+ +
Class + return_opaque_pointer metafunctions
+
+
+
+
+ +
Example
+ +
See Also
+
+
+ +

Classes

+ +

Class + return_opaque_pointer

+ +

return_opaque_pointer is a model of + + ResultConverterGenerator + which can be used to wrap C++ functions returning pointers to + undefined types such that the return value is copied into a + new Python object.

+

In addition to specifying the return_opaque_pointer + policy the + BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID macro must be + used to define specializations for the + type_id function + on the type pointed to by returned pointer.

+ +

Class + return_opaque_pointer synopsis

+
+namespace boost { namespace python
+{
+    struct return_opaque_pointer
+    {
+        template <class R> struct apply;
+    };
+}}
+
+ +

Class + return_opaque_pointer metafunctions

+
+template <class R> struct apply
+
+ +
+
Returns: typedef + detail::opaque_conversion_holder<R> + type;
+
+ +

Example

+ +

C++ Module Definition

+
+# include <boost/python/return_opaque_pointer.hpp>
+# include <boost/python/def.hpp>
+# include <boost/python/module.hpp>
+# include <boost/python/return_value_policy.hpp>
+
+typedef struct opaque_ *opaque;
+
+opaque the_op   = ((opaque) 0x47110815);
+
+opaque get () { return the_op; }
+void use (opaque op) {
+    if (op != the_op)
+	throw std::runtime_error (std::string ("failed"));
+}
+
+void failuse (opaque op) {
+    if (op == the_op)
+	throw std::runtime_error (std::string ("success"));
+}
+
+BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
+
+namespace bpl = boost::python;
+
+BOOST_PYTHON_MODULE(opaque_ext)
+{
+    bpl::def (
+        "get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
+    bpl::def ("use", &::use);
+    bpl::def ("failuse", &::failuse);
+}
+
+ +

Python Code

+
+"""
+>>> from opaque_ext import *
+>>> #
+>>> # Check for correct conversion
+>>> use(get())
+>>> failuse(get())
+Traceback (most recent call last):
+        ...
+RuntimeError: success
+>>> #
+>>> # Check that there is no conversion from integers ...
+>>> use(0)
+Traceback (most recent call last):
+        ...
+TypeError: bad argument type for built-in operation
+>>> #
+>>> # ... and from strings to opaque objects
+>>> use("")
+Traceback (most recent call last):
+        ...
+TypeError: bad argument type for built-in operation
+"""
+def run(args = None):
+    import sys
+    import doctest
+
+    if args is not None:
+        sys.argv = args
+    return doctest.testmod(sys.modules.get(__name__))
+    
+if __name__ == '__main__':
+    print "running..."
+    import sys
+    sys.exit(run()[0])
+
+ +

See Also

+

+ + opaque +

+ +

Revised + 28 January, 2003 +

+ +

© Copyright 2003 Haufe Mediengruppe. All Rights + Reserved.

+ + + diff --git a/libs/python/doc/v2/return_value_policy.html b/libs/python/doc/v2/return_value_policy.html new file mode 100644 index 0000000000..b02d4bc39d --- /dev/null +++ b/libs/python/doc/v2/return_value_policy.html @@ -0,0 +1,167 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/return_value_policy.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/return_value_policy.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class Template + return_value_policy
+ +
+
+
Class Template + return_value_policy synopsis
+
+
+
+
+ +
Example
+
+
+ +

Introduction

+ return_value_policy instantiations are simply models of CallPolicies which are composed of a ResultConverterGenerator + and optional Base CallPolicies. + +

Classes

+ +

Class template + return_value_policy

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ return_value_policy template parameters +
ParameterRequirementsDefault
ResultConverterGeneratorA model of ResultConverterGenerator.
BaseA model of CallPoliciesdefault_call_policies
+ +

Class template + return_value_policy synopsis

+
+namespace boost { namespace python
+{
+  template <class ResultConverterGenerator, class Base = default_call_policies>
+  struct return_value_policy : Base
+  {
+      typedef ResultConverterGenerator result_converter;
+  };
+}}
+
+ +

Example

+ +

C++ Module Definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/copy_const_reference.hpp>
+#include <boost/python/return_value_policy.hpp>
+
+// classes to wrap
+struct Bar { int x; }
+
+struct Foo {
+   Foo(int x) : { b.x = x; }
+   Bar const& get_bar() const { return b; }
+ private:
+   Bar b;
+};
+
+// Wrapper code
+using namespace boost::python;
+BOOST_PYTHON_MODULE(my_module)
+{
+   class_<Bar>("Bar");
+
+   class_<Foo>("Foo", init<int>())
+      .def("get_bar", &Foo::get_bar
+          , return_value_policy<copy_const_reference>())
+      ;
+}
+
+ +

Python Code

+
+>>> from my_module import *
+>>> f = Foo(3)         # create a Foo object
+>>> b = f.get_bar()    # make a copy of the internal Bar object
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/scope.html b/libs/python/doc/v2/scope.html new file mode 100644 index 0000000000..54ef67e3e9 --- /dev/null +++ b/libs/python/doc/v2/scope.html @@ -0,0 +1,173 @@ + + + + + + + + + + + + Boost.Python - <boost/python/scope.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/scope.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class scope
+ +
+
+
Class scope + synopsis
+ +
Class scope + constructors and destructor
+
+
+
+
+ +
Example
+
+
+ +

Introduction

+ +

Defines facilities for querying and controlling the Python scope + (namespace) which will contain new wrapped classes and functions.

+ +

Classes

+ +

Class scope

+ +

The scope class has an associated global Python + object which controls the Python namespace in which new extension + classes and wrapped functions will be defined as + attributes. Default-constructing a new scope object + binds it to the associated global Python object. Constructing a + scope object with an argument changes the associated + global Python object to the one held by the argument, until the + lifetime of the scope object ends, at which time the + associated global Python object reverts to what it was before the + scope object was constructed.

+ +

Class scope + synopsis

+
+namespace boost { namespace python
+{
+  class scope : public object
+  {
+   public:
+      scope(scope const&);
+      scope(object const&);
+      scope();
+      ~scope()
+   private:
+      void operator=(scope const&);
+  };
+}}
+
+ +

Class scope constructors + and destructor

+
+explicit scope(scope const& x);
+explicit scope(object const& x);
+
+ Stores a reference to the current associated scope object, and sets the + associated scope object to the one referred to by x.ptr(). + The object base class is initialized with x. +
+scope();
+
+ Stores a reference to the current associated scope object. The + object base class is initialized with the current associated + scope object. Outside any module initialization function, the current + associated Python object is None. +
+~scope()
+
+ Sets the current associated Python object to the stored object. + +

Example

+ The following example shows how scope setting can be used to define + nested classes. + +

C++ Module definition:

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/scope.hpp>
+using namespace boost::python;
+
+struct X
+{
+  void f() {}
+
+  struct Y { int g() { return 42; } };
+};
+
+BOOST_PYTHON_MODULE(nested)
+{
+   // add some constants to the current (module) scope
+   scope().attr("yes") = 1;
+   scope().attr("no") = 0;
+
+   // Change the current scope 
+   scope outer
+       = class_<X>("X")
+            .def("f", &X::f)
+            ;
+
+   // Define a class Y in the current scope, X
+   class_<X::Y>("Y")
+      .def("g", &X::Y::g)
+      ;
+}
+
+ Interactive Python: +
+>>> import nested
+>>> nested.yes
+1
+>>> y = nested.X.Y()
+>>> y.g()
+42
+
+ +

Revised 09 October, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/slice.html b/libs/python/doc/v2/slice.html new file mode 100644 index 0000000000..fb6b47c7e3 --- /dev/null +++ b/libs/python/doc/v2/slice.html @@ -0,0 +1,246 @@ + + + + + + + + + + Boost.Python - <boost/python/slice.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+

Header <boost/python/slice.hpp>

+
+
+

Contents

+
+
Introduction
+
Classes
+
+
+
Class slice
+
+
+
Class slice +synopsis
+
Class slice +constructors
+
Class slice +observer functions
+
+
+
+
+
Example(s)
+
+
+

Introduction

+

Exposes a TypeWrapper +for the Python slice +type.

+

Classes

+

Class slice

+

Exposes the extended slicing protocol by wrapping the built-in slice +type. The semantics of the constructors and member functions defined +below can be fully understood by reading the TypeWrapper concept +definition. Since slice is publicly derived from object, the public object +interface applies to slice instances as well.
+

+

Class slice synopsis

+
+namespace boost { namespace python
+{
+  class slice : public object
+  {
+   public:
+      slice(); // create an empty slice, equivalent to [::]
+
+      template <typename Int1, typename Int2>
+      slice(Int1 start, Int2 stop);
+
+      template <typename Int1, typename Int2, typename Int3>
+      slice(Int1 start, Int2 stop, Int3 step);
+
+      // Access the parameters this slice was created with.
+      object start();
+      object stop();
+      object step();
+
+      // The return type of slice::get_indices()
+      template <typename RandomAccessIterator>
+      struct range
+      {
+          RandomAccessIterator start;
+          RandomAccessIterator stop;
+          int step;
+      };
+
+      template <typename RandomAccessIterator>
+      range<RandomAccessIterator>
+      get_indices(
+          RandomAccessIterator const& begin, 
+          RandomAccessIterator const& end);
+  };
+}}
+
+

Class slice +constructors
+

+
slice();
+
+
Effects: constructs a slice with default stop, start, and +step values.  Equivalent to the slice object created as part of the Python +expression base[::].
+
Throws: nothing.
+
+
+template <typename Int1, typename Int2>
+slice(Int1 start, Int2 stop);
+
+
+
Requires: start, stop, and step + are of type slice_nil + or convertible to type object.
+
Effects: constructs a new slice with default step value +and the provided start and stop values.  Equivalent to the slice +object +created by the built-in Python function slice(start,stop), +or as part of the Python expression base[start:stop].
+
Throws: error_already_set and sets a Python TypeError +exception if no conversion is possible from the arguments to type object.
+
+
+template <typename Int1, typename Int2, typename Int3>
+slice(Int1 start, Int2 stop, Int3 step);
+
+
Requires: start, stop, and step are slice_nil or convertible to type object.
+
Effects: constructs a new slice with start stop and step +values.  Equivalent to the slice object created +by the built-in Python function slice(start,stop,step), +or as part of the Python expression base[start:stop:step].
+
Throws: error_already_set and sets a Python TypeError +exception if no conversion is possible from the arguments to type +object.
+

Class slice +observer functions
+

+
+object slice::start() const;
+object slice::stop() const;
+object slice::step() const;
+
+
+
Effects: None.
+
Throws: nothing.
+
Returns:the parameter that +the slice was created with. If the parameter was omitted or +slice_nil was used when the slice was created, than that parameter will +be a reference to PyNone and compare equal to a default-constructed +object.  In principal, any object may be used when creating a +slice object, but in practice they are usually integers.
+
+
+
+template <typename RandomAccessIterator>
+slice::range<RandomAccessIterator>
+slice::get_indices( 
+    RandomAccessIterator const& begin, 
+    RandomAccessIterator const& end) const;
+
+
+
Arguments: A pair of STL-conforming Random Access +Iterators that form a half-open range.
+
Effects: Create a RandomAccessIterator pair that defines a +fully-closed range within the [begin,end) range of its arguments.  +This function translates this slice's indices while accounting for the +effects of any PyNone or negative indices, and non-singular step sizes.
+
Returns: a slice::range +that has been initialized with a non-zero value of step and a pair of +RandomAccessIterators that point within the range of this functions +arguments and define a closed interval.
+
Throws: Raises a Python TypeError exception if any of this slice's arguments +are neither references to PyNone nor convertible to int.  Throws +std::invalid_argument if the resulting range would be empty.  You +should always wrap calls to slice::get_indices() +within try { ...; } catch (std::invalid_argument) {} to +handle this case and take appropriate action.
+
Rationale: closed-interval: If +an open interval were used, then for step +size other than 1, the required state for the end iterator would point +beyond the one-past-the-end position or before the beginning of the +specified range.
+exceptions on empty slice: It is impossible to define a closed interval +over an empty range, so some other form of error checking would have to +be used to prevent undefined behavior. In the case where the +exception is not caught, it will simply be translated to Python by the +default exception handling mechanisms.
+
+

Examples

+
+using namespace boost::python;
+
+// Perform an extended slice of a Python list.
+// Warning: extended slicing was not supported for built-in types prior 
+// to Python 2.3
+list odd_elements(list l)
+{
+    return l[slice(_,_,2)];
+}
+
+// Perform a multidimensional extended slice of a Numeric.array
+numeric::array even_columns(numeric::array arr)
+{
+    // select every other column, starting with the second, of a 2-D array.
+    // Equivalent to "return arr[:, 1::2]" in Python.
+    return arr[make_tuple( slice(), slice(1,_,2))];
+}
+
+// Perform a summation over a slice of a std::vector.
+double partial_sum(std::vector<double> const& Foo, const slice index)
+{
+    slice::range<std::vector<double>::const_iterator> bounds;
+    try {
+        bounds = index.get_indices<>(Foo.begin(), Foo.end());
+    }
+    catch (std::invalid_argument) {
+        return 0.0;
+    }
+    double sum = 0.0;
+    while (bounds.start != bounds.stop) {
+        sum += *bounds.start;
+        std::advance( bounds.start, bounds.step);
+    }
+    sum += *bounds.start;
+    return sum;
+}
+
+

Revised 07 Febuary, 2004

+

© Copyright Jonathan Brandmeyer, +2004.  Modification, copying and redistribution of this document +is permitted under the terms and conditions of the Boost Software +License, version 1.0.
+

+ + diff --git a/libs/python/doc/v2/ssize_t.html b/libs/python/doc/v2/ssize_t.html new file mode 100644 index 0000000000..cb4398bb58 --- /dev/null +++ b/libs/python/doc/v2/ssize_t.html @@ -0,0 +1,96 @@ + + + + + + + + + + + + Boost.Python - <boost/python/ssize_t.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/ssize_t.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Typedef
+ +
Constants
+
+
+ +

Introduction

+ +

Python 2.5 introduces a new Py_ssize_t typedef and + two related macros (PEP 353). The + <boost/python/ssize_t.hpp> header imports these + definitions into the boost::python namespace as + ssize_t, ssize_t_max, and ssize_t_min. + Appropriate definitions are provided for backward compatibility + with previous Python versions.

+ +

Typedefs

Imports + Py_ssize_t into the boost::python namespace if + available, or provides an appropriate typedef for backward + compatibility: +
+#if PY_VERSION_HEX >= 0x02050000
+typedef Py_ssize_t ssize_t;
+#else
+typedef int ssize_t;
+#endif
+
+ +

Constants

Imports + PY_SSIZE_T_MAX and PY_SSIZE_T_MIN as constants + into the boost::python namespace if available, or + provides appropriate constants for backward compatibility: +
+#if PY_VERSION_HEX >= 0x02050000
+ssize_t const ssize_t_max = PY_SSIZE_T_MAX;
+ssize_t const ssize_t_min = PY_SSIZE_T_MIN;
+#else
+ssize_t const ssize_t_max = INT_MAX;
+ssize_t const ssize_t_min = INT_MIN;
+#endif
+
+ +

Revised + + 25 September, 2006 +

+ +

© Copyright Ralf W. + Grosse-Kunstleve 2006.

+ + diff --git a/libs/python/doc/v2/stl_iterator.html b/libs/python/doc/v2/stl_iterator.html new file mode 100644 index 0000000000..ef197b0f82 --- /dev/null +++ b/libs/python/doc/v2/stl_iterator.html @@ -0,0 +1,273 @@ + + + + + + + + + Boost.Python - <boost/python/stl_iterator.hpp> + + + + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/stl_iterator.hpp>

+
+
+ +

Contents

+
+
Introduction
+ +
Classes
+ +
+
+
Class template + stl_input_iterator
+ +
+
+
Class + stl_input_iterator synopsis
+ +
Class template + stl_input_iterator constructors
+ +
Class template + stl_input_iterator modifiers
+ +
Class template + stl_input_iterator observers
+
+
+
+
+ +
Examples
+
+
+ +

Introduction

+ +

<boost/python/stl_iterator.hpp> provides types + for creating C++ + Iterators from + Python iterables.

+ +

Classes

+ +

Class Template + stl_input_iterator

+ +

Instances of stl_input_iterator<T> hold a Python + iterator and adapt it for use with STL algorithms. + stl_input_iterator<T> satisfies the requirements for + an Input Iterator. +

+ + + + + + + + + + + + + + + + + + + + + +
Template ParameterRequirementsSemanticsDefault
ValueTypeValueType must be CopyConstructible.Dereferencing an instance of stl_input_iterator<ValueType> + will return an rvalue of type ValueType.None
+ +

Class Template stl_input_iterator + synopsis

+ +
+namespace boost { namespace python
+{
+  template <class ValueType>
+  struct stl_input_iterator
+  {
+      typedef std::ptrdiff_t difference_type;
+      typedef ValueType value_type;
+      typedef ValueType* pointer;
+      typedef ValueType reference;
+      typedef std::input_iterator_tag iterator_category;
+
+      stl_input_iterator();
+      stl_input_iterator(object const& ob);
+
+      stl_input_iterator& operator++();
+      stl_input_iterator operator++(int);
+
+      ValueType operator*() const;
+
+      friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& rhs);
+      friend bool operator!=(stl_input_iterator const& lhs, stl_input_iterator const& rhs);
+  private:
+      object it; // For exposition only
+      object ob; // For exposition only
+  };
+}}
+
+ +

+ Class Template stl_input_iterator + constructors +

+ +
+stl_input_iterator()
+
+ +
+
Effects: + Creates a past-the-end input iterator, useful for signifying the end of a sequence. +
+
Postconditions: this is past-the-end.
+
Throws: Nothing.
+
+ +
+stl_input_iterator(object const& ob)
+
+ +
+
Effects: + Calls ob.attr("__iter__")() and stores the resulting Python iterator + object in this->it. Then, calls this->it.attr("next")() and + stores the result in this->ob. If the sequence is exhausted, sets + this->ob to object(). +
+ +
Postconditions: this is a dereferenceable or past-the-end.
+
+ +

+ Class Template stl_input_iterator + modifiers +

+ +
+stl_input_iterator& operator++()
+
+ +
+
Effects: + Calls this->it.attr("next")() and stores the result in + this->ob. If the sequence is exhausted, sets this->ob + to object(). +
+ +
Postconditions: this is a dereferenceable or past-the-end.
+ +
Returns: *this.
+
+ +
+stl_input_iterator operator++(int)
+
+ +
+
Effects: + stl_input_iterator tmp = *this; ++*this; return tmp; +
+ +
Postconditions: this is a dereferenceable or past-the-end.
+
+ +

Class Templatestl_input_iterator + observers

+ +
+ValueType operator*() const
+
+ +
+
Effects: + Returns the current element in the sequence. +
+
Returns: + extract<ValueType>(this->ob); +
+
+ +
+friend bool operator==(stl_input_iterator const& lhs, stl_input_iterator const& rhs)
+
+ +
+
Effects: + Returns true if both iterators are dereferenceable or if both iterators are past-the-end, + false otherwise. +
+
Returns: + (lhs.ob == object()) == (rhs.ob == object()) +
+
+ +
+friend bool operator!=(stl_input_iterator const& lhs, stl_input_iterator const& rhs)
+
+ +
+
Effects: + Returns false if both iterators are dereferenceable or if both iterators are past-the-end, + true otherwise. +
+
Returns: + !(lhs == rhs) +
+
+ +

Examples

+
+#include <boost/python/object.hpp>
+#include <boost/python/stl_iterator.hpp>
+
+#include <list>
+
+using namespace boost::python;
+std::list<int> sequence_to_int_list(object const& ob)
+{
+    stl_input_iterator<int> begin(ob), end;
+    return std::list<int>(begin, end);
+}
+
+ +
+

Revised + 30 +October, 2005 + +

+ +

Copyright Eric Niebler 2005.

+ + \ No newline at end of file diff --git a/libs/python/doc/v2/str.html b/libs/python/doc/v2/str.html new file mode 100644 index 0000000000..11810d8418 --- /dev/null +++ b/libs/python/doc/v2/str.html @@ -0,0 +1,237 @@ + + + + + + + + + + + + Boost.Python - <boost/python/str.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/str.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class str
+ +
+
+
Class str + synopsis
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

Exposes a TypeWrapper for the Python + str + type.

+ +

Classes

+ +

Class str

+ +

Exposes the string + methods of Python's built-in str type. The + semantics of the constructors and member functions defined below, + except for the two-argument constructors which construct str + objects from a range of characters, can be fully understood by + reading the TypeWrapper concept + definition. Since str is publicly derived from + object, the + public object interface applies to str instances as + well.

+ +

Class str + synopsis

+
+namespace boost { namespace python
+{
+  class str : public object
+  {
+   public:
+      str(); // new str
+
+      str(char const* s); // new str
+
+      str(char const* start, char const* finish); // new str
+      str(char const* start, std::size_t length); // new str
+
+      template <class T>
+      explicit str(T const& other);
+
+      str capitalize() const;
+
+      template <class T>
+      str center(T const& width) const;
+
+      template<class T>
+      long count(T const& sub) const;
+      template<class T1, class T2>
+      long count(T1 const& sub,T2 const& start) const;
+      template<class T1, class T2, class T3>
+      long count(T1 const& sub,T2 const& start, T3 const& end) const;
+
+      object decode() const;
+      template<class T>
+      object decode(T const& encoding) const;
+      template<class T1, class T2>
+      object decode(T1 const& encoding, T2 const& errors) const;
+
+      object encode() const;
+      template <class T>
+      object encode(T const& encoding) const;
+      template <class T1, class T2>
+      object encode(T1 const& encoding, T2 const& errors) const;
+
+      template <class T>
+      bool endswith(T const& suffix) const;
+      template <class T1, class T2>
+      bool endswith(T1 const& suffix, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      bool endswith(T1 const& suffix, T2 const& start, T3 const& end) const;
+
+      str expandtabs() const;
+      template <class T>
+      str expandtabs(T const& tabsize) const;
+
+      template <class T>
+      long find(T const& sub) const;
+      template <class T1, class T2>
+      long find(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long find(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      template <class T>
+      long index(T const& sub) const;
+      template <class T1, class T2>
+      long index(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long index(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      bool isalnum() const;
+      bool isalpha() const;
+      bool isdigit() const;
+      bool islower() const;
+      bool isspace() const;
+      bool istitle() const;
+      bool isupper() const;
+
+      template <class T>
+      str join(T const& sequence) const;
+
+      template <class T>
+      str ljust(T const& width) const;
+
+      str lower() const;
+      str lstrip() const;
+
+      template <class T1, class T2>
+      str replace(T1 const& old, T2 const& new_) const;
+      template <class T1, class T2, class T3>
+      str replace(T1 const& old, T2 const& new_, T3 const& maxsplit) const;
+
+      template <class T>
+      long rfind(T const& sub) const;
+      template <class T1, class T2>
+      long rfind(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long rfind(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      template <class T>
+      long rindex(T const& sub) const;
+      template <class T1, class T2>
+      long rindex(T1 const& sub, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      long rindex(T1 const& sub, T2 const& start, T3 const& end) const;
+
+      template <class T>
+      str rjust(T const& width) const;
+
+      str rstrip() const;
+
+      list split() const; 
+      template <class T>
+      list split(T const& sep) const;
+      template <class T1, class T2>
+      list split(T1 const& sep, T2 const& maxsplit) const;
+
+      list splitlines() const;
+      template <class T>
+      list splitlines(T const& keepends) const;
+
+      template <class T>
+      bool startswith(T const& prefix) const;
+      template <class T1, class T2>
+      bool startswidth(T1 const& prefix, T2 const& start) const;
+      template <class T1, class T2, class T3>
+      bool startswidth(T1 const& prefix, T2 const& start, T3 const& end) const;
+
+      str strip() const;
+      str swapcase() const;
+      str title() const;
+
+      template <class T>
+      str translate(T const& table) const;
+      template <class T1, class T2>
+      str translate(T1 const& table, T2 const& deletechars) const;
+
+      str upper() const;
+  };
+}}
+
+ +

Example

+
+using namespace boost::python;
+str remove_angle_brackets(str x)
+{
+  return x.strip('<').strip('>');
+}
+
+ +

Revised 3 October, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/to_python_converter.html b/libs/python/doc/v2/to_python_converter.html new file mode 100644 index 0000000000..81b61d252b --- /dev/null +++ b/libs/python/doc/v2/to_python_converter.html @@ -0,0 +1,227 @@ + + + + + + + + + + + + Boost.Python - + <boost/python/to_python_converter.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header + <boost/python/to_python_converter.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class Template + to_python_converter
+ +
+
+
Class Template + to_python_converter synopsis
+ +
Class Template + to_python_converter constructor
+
+
+
+
+ +
Example
+
+
+ +

Introduction

+ to_python_converter registers a conversion from objects of a + given C++ type into a Python object. + +

Classes

+ +

Class template + to_python_converter

+ to_python_converter adds a wrapper around a static member + function of its second template parameter, handling low-level details + such as insertion into the converter registry. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ to_python_converter template parameters
+ In the table below, x denotes an object of type + T +
ParameterRequirementsDescription
T + The C++ type of the source object in the conversion
Conversion + PyObject* p = Conversion::convert(x),
+ if p == 0, PyErr_Occurred() != 0.
A class type whose static member function convert + does the real work of the conversion.
bool has_get_pytype = false + PyTypeObject const * p = Conversion::get_pytype() .Optional member - if Conversion has get_pytype member supply + true for this parameters. + If present get_pytype is used to document the return type + of functions using this conversion. The get_pytype may be implemented + using the classes and functions + from pytype_function.hpp + NOTE : For backward compatibility this parameter may be passed after + checking if BOOST_PYTHON_SUPPORTS_PY_SIGNATURES is defined (see + here). +
+ +

Class template + to_python_converter synopsis

+
+namespace boost { namespace python
+{
+  template <class T, class Conversion, bool convertion_has_get_pytype_member=false>
+  struct to_python_converter
+  {
+      to_python_converter();
+  };
+}}
+
+ +

Class template + to_python_converter constructor

+
+to_python_converter();
+
+ +
+
Effects: Registers a to_python converter which uses + Conversion::convert() to do its work.
+
+ +

Example

+ This example presumes that someone has implemented the standard noddy example + module from the Python documentation, and placed the corresponding + declarations in "noddy.h". Because + noddy_NoddyObject is the ultimate trivial extension type, + the example is a bit contrived: it wraps a function for which all + information is contained in the type of its return value. + +

C++ module definition

+
+#include <boost/python/reference.hpp>
+#include <boost/python/module.hpp>
+#include "noddy.h"
+
+struct tag {};
+tag make_tag() { return tag(); }
+
+using namespace boost::python;
+
+struct tag_to_noddy
+{
+    static PyObject* convert(tag const& x)
+    {
+        return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
+    }
+    static PyTypeObject const* get_pytype()
+    {
+        return &noddy_NoddyType;
+    }
+};
+
+BOOST_PYTHON_MODULE(to_python_converter)
+{
+    def("make_tag", make_tag);
+    to_python_converter<tag, tag_to_noddy, true>(); //"true" because tag_to_noddy has member get_pytype
+}
+
+ +

Python code

+
+>>> import to_python_converter
+>>> def always_none():
+...     return None
+...
+>>> def choose_function(x):
+...     if (x % 2 != 0):
+...         return to_python_converter.make_tag
+...     else:
+...         return always_none
+...
+>>> a = [ choose_function(x) for x in range(5) ]
+>>> b = [ f() for f in a ]
+>>> type(b[0])
+<type 'NoneType'>
+>>> type(b[1])
+<type 'Noddy'>
+>>> type(b[2])
+<type 'NoneType'>
+>>> type(b[3])
+<type 'Noddy'>
+
+ +

Revised + + 11 June, 2007 + +

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/to_python_indirect.html b/libs/python/doc/v2/to_python_indirect.html new file mode 100644 index 0000000000..17e0a826c4 --- /dev/null +++ b/libs/python/doc/v2/to_python_indirect.html @@ -0,0 +1,196 @@ + + + + + + Boost.Python - <boost/python/to_python_indirect.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header <boost/python/to_python_indirect.hpp>

+
+
+ +

Contents

+ +
+
Introduction + + +
Classes + +
+
+
Class Template to_python_indirect + +
+
+ +
Class Template + to_python_indirect synopsis + +
Class Template + to_python_indirect observer functions + +
Class Template + to_python_indirect static functions +
+
+ +
Example +
+
+ +

Introduction

+ + <boost/python/to_python_indirect.hpp> supplies + a way to construct new Python objects that hold wrapped C++ class + instances via a pointer or smart pointer. + +

Classes

+ +

Class template to_python_indirect

+

Class template to_python_indirect converts objects +of its first argument type to python as extension class instances, using the ownership policy provided by its 2nd argument. + +

+ + + + + + + +
+ to_python_indirect Requirements
+ + In the table below, x denotes an object of + type T, h denotes an + object of type + boost::python::objects::instance_holder*, and + p denotes an object of type + U*. + +
Parameter + + Requirements + + Description + +
T + + Either U cv& + (where cv is any optional cv-qualification) or a Dereferenceable type such that + *x is convertible to U const&, where + U is a class type. + + A type deferencing a C++ class exposed to Python using + class template class_. + +
MakeHolder + + h = MakeHolder::execute(p); + + A class whose static execute() creates an + instance_holder. + +
+ + Instantiations of to_python_indirect are models of ResultConverter. + + +

Class template to_python_indirect synopsis

+
+namespace boost { namespace python
+{
+  template <class T, class MakeHolder>
+  struct to_python_indirect
+  {
+     static bool convertible();
+     PyObject* operator()(T ptr_or_reference) const;
+   private:
+     static PyTypeObject* type();
+  };
+}}
+
+ +

Class template to_python_indirect observers

+
+PyObject* operator()(T x) const;
+
+ +
+ +
Requires: x refers to an object (if it + is a pointer type, it is non-null). convertible() == + true. + +
Effects: Creates an appropriately-typed Boost.Python + extension class instance, uses MakeHolder to create + an instance_holder from x, installs + the instance_holder in the new extension class + instance, and returns a pointer to it. + +
+ + +

Class template to_python_indirect statics

+
+bool convertible();
+
+ +
Effects: Returns true iff any module has + registered a Python type corresponding to U. + +

Example

+ +This example replicates the functionality of reference_existing_object, +but without some of the compile-time error checking. + + +
+
+struct make_reference_holder
+{
+   typedef boost::python::objects::instance_holder* result_type;
+   template <class T>
+   static result_type execute(T* p)
+   {
+      return new boost::python::objects::pointer_holder<T*, T>(p);
+   }
+};
+
+struct reference_existing_object
+{
+   // metafunction returning the ResultConverter
+   template <class T>
+   struct apply
+   {
+      typedef boost::python::to_python_indirect<T,make_reference_holder> type;
+   };
+};
+
+ +

Revised + + 13 November, 2002 + + + +

© Copyright Dave + Abrahams 2002. 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)

+ diff --git a/libs/python/doc/v2/to_python_value.html b/libs/python/doc/v2/to_python_value.html new file mode 100644 index 0000000000..3ba0044d1d --- /dev/null +++ b/libs/python/doc/v2/to_python_value.html @@ -0,0 +1,103 @@ + + + + + + Boost.Python - <boost/python/to_python_value.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header + <boost/python/to_python_value.hpp>

+
+
+ +

Contents

+ +
+
Classes + +
+
+
Class + to_python_value + +
+
+
Class template + to_python_value synopsis + +
Class template + to_python_value observer functions +
+
+ +
+
+ +

Classes

+ +

Class template + to_python_value

+ +

to_python_value is a model of ResultConverter + which copies its argument into a new Python object. + +

Class + to_python_value synopsis

+
+namespace boost { namespace python
+{
+   template <class T>
+   struct to_python_value
+   {
+      typedef typename add_reference<
+         typename add_const<T>::type
+      >::type argument_type;
+
+      static bool convertible();
+      PyObject* operator()(argument_type) const;
+   };
+}}
+
+ +

Class + to_python_value observers

+
+static bool convertible();
+
+ +
+
Returns: true iff a converter has been registered which can convert T to python by-value. +
+ +
+PyObject* operator()(argument_type x) const;
+
+ +
+
Requires: convertible() == true +
Effects: converts x to python +
Returns: the resulting Python object iff a converter for T has been registered, 0 otherwise. +
+ +

Revised + + 13 November, 2002 + + + +

© Copyright Dave + Abrahams 2002. 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)

+ diff --git a/libs/python/doc/v2/tuple.html b/libs/python/doc/v2/tuple.html new file mode 100644 index 0000000000..e90244f3e4 --- /dev/null +++ b/libs/python/doc/v2/tuple.html @@ -0,0 +1,139 @@ + + + + + + + + + + + + Boost.Python - <boost/python/tuple.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/tuple.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class tuple
+ +
+
+
Class tuple + synopsis
+
+
+
+
+ +
Functions
+ +
+
+
make_tuple
+
+
+ +
Example
+
+
+ +

Introduction

+ +

Exposes a TypeWrapper for the Python + + tuple type.

+ +

Classes

+ +

Class tuple

+ +

Exposes the interface of Python's built-in tuple type. + The semantics of the constructors and member functions defined below can + be fully understood by reading the TypeWrapper concept + definition. Since tuple is publicly derived from object, the public object + interface applies to tuple instances as well.

+ +

Class tuple + synopsis

+
+namespace boost { namespace python
+{
+   class tuple : public object
+   {
+      // tuple() -> an empty tuple
+      tuple();
+
+      // tuple(sequence) -> tuple initialized from sequence's items
+      template <class T>
+      explicit tuple(T const& sequence)
+  };
+}}
+
+ +

Functions

+ +

make_tuple

+
+namespace boost { namespace python
+{
+  tuple make_tuple();
+
+  template <class A0>
+  tuple make_tuple(A0 const& a0);
+
+  template <class A0, class A1>
+  tuple make_tuple(A0 const& a0, A1 const& a1);
+  ...
+  template <class A0, class A1,...class An> 
+  tuple make_tuple(A0 const& a0, A1 const& a1,...An const& an);
+}}
+
+ Constructs a new tuple object composed of object(a0), + object(a0),...object(an). + +

Example

+
+using namespace boost::python;
+tuple head_and_tail(object sequence)
+{
+    return make_tuple(sequence[0],sequence[-1]);
+}
+
+ +

Revised 03 October, 2002

+ +

© Copyright Dave Abrahams 2002.

+ + + diff --git a/libs/python/doc/v2/type_id.html b/libs/python/doc/v2/type_id.html new file mode 100644 index 0000000000..570846741c --- /dev/null +++ b/libs/python/doc/v2/type_id.html @@ -0,0 +1,224 @@ + + + + + + + Boost.Python - <boost/python/type_id.hpp> + + + + + +
+

C++ Boost

+ +
+

Boost.Python

+ +

Header <boost/python/type_id.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class type_info
+ +
+
+
Class + type_info synopsis
+ +
Class type_info + constructor
+ +
Class + type_info comparison functions
+ +
Class + type_info observer functions
+
+
+
+
+ +
Functions
+ +
+
+
type_id
+
+
+ +
Example
+
+
+ +

Introduction

+ +

<boost/python/type_id.hpp> provides types and + functions for runtime type identification like those of of + <typeinfo>. It exists mostly to work around certain + compiler bugs and platform-dependent interactions with shared + libraries.

+ +

Classes

+ +

Class type_info

+ +

type_info instances identify a type. As + std::type_info is specified to (but unlike its + implementation in some compilers), boost::python::type_info + never represents top-level references or cv-qualification (see section + 5.2.8 in the C++ standard). Unlike std::type_info, + boost::python::type_info instances are copyable, and + comparisons always work reliably across shared library boundaries.

+ +

Class type_info synopsis

+
+namespace boost { namespace python
+{
+  class type_info : totally_ordered<type_info>
+  {
+   public:
+      // constructor
+      type_info(std::type_info const& = typeid(void));
+
+      // comparisons
+      bool operator<(type_info const& rhs) const;
+      bool operator==(type_info const& rhs) const;
+
+      // observers
+      char const* name() const;
+  };
+}}
+
+ +

Class type_info + constructor

+
+type_info(std::type_info const& = typeid(void));
+
+ +
+
Effects: constructs a type_info object which + identifies the same type as its argument.
+ +
Rationale: Since it is occasionally necessary to make an + array of type_info objects a benign default argument is + supplied. Note: this constructor does + not correct for non-conformance of compiler + typeid() implementations. See type_id, below.
+
+ +

Class type_info + comparisons

+
+bool operator<(type_info const& rhs) const;
+
+ +
+
Effects: yields a total order over type_info + objects.
+
+
+bool operator==(type_info const& rhs) const;
+
+ +
+
Returns: true iff the two values describe the + same type.
+
+ +
+
Note: The use of totally_ordered<type_info> + as a private base class supplies operators <=, + >=, >, and !=
+
+ +

Class type_info + observers

+
+char const* name() const;
+
+ +
+
Returns: The result of calling name() on the + argument used to construct the object.
+
+ +

Functions

+
+std::ostream& operator<<(std::ostream&s, type_info const&x);
+
+ +
+
Effects: Writes a description of the type described by to + x into s.
+ +
Rationale: Not every C++ implementation provides a truly + human-readable type_info::name() string, but for some we + may be able to decode the string and produce a reasonable + representation.
+
+
+template <class T> type_info type_id()
+
+ +
+
Returns: type_info(typeid(T))
+ +
Note: On some non-conforming C++ implementations, the code + is not actually as simple as described above; the semantics are + adjusted to work as-if the C++ implementation were + conforming.
+
+ +

Example

+ The following example, though silly, illustrates how the + type_id facility might be used +
+#include <boost/python/type_id.hpp>
+
+// Returns true iff the user passes an int argument
+template <class T>
+bool is_int(T x)
+{
+   using boost::python::type_id;
+   return type_id<T>() == type_id<int>();
+}
+
+ +

Revised + + 13 November, 2002 + +

+ +

© Copyright Dave Abrahams 2002. 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)< + + + + diff --git a/libs/python/doc/v2/with_custodian_and_ward.html b/libs/python/doc/v2/with_custodian_and_ward.html new file mode 100644 index 0000000000..b8e2a498db --- /dev/null +++ b/libs/python/doc/v2/with_custodian_and_ward.html @@ -0,0 +1,370 @@ + + + + + + + + + + + Boost.Python - <boost/python/with_custodian_and_ward.hpp> + + + + + + + + +
+

+ C++ Boost + +

+
+

+ Boost.Python +

+

+ Header <boost/python/with_custodian_and_ward.hpp> +

+
+


+

+ Contents +

+
+
+ Introduction +
+
+ Classes +
+
+
+
+ Class Template + with_custodian_and_ward +
+
+
+
+ Class + Template with_custodian_and_ward synopsis +
+
+ Class + with_custodian_and_ward static functions +
+
+
+
+ Class Template + with_custodian_and_ward_postcall +
+
+
+
+ Class + Template with_custodian_and_ward_postcall + synopsis +
+
+ Class + with_custodian_and_ward_postcall static + functions +
+
+
+
+
+
+ Example +
+
+
+

+ Introduction +

This header provides facilities for establishing a lifetime + dependency between two of a function's Python argument or result objects. + The ward object will not be destroyed until after the custodian as + long as the custodian object supports weak + references (Boost.Python extension classes all support weak + references). If the custodian object does not support weak + references and is not None, an appropriate exception will be + thrown. The two class templates with_custodian_and_ward and + with_custodian_and_ward_postcall differ in the point at + which they take effect. +

+ In order to reduce the chance of inadvertently creating dangling + pointers, the default is to do lifetime binding before the + underlying C++ object is invoked. However, before invocation the result + object is not available, so + with_custodian_and_ward_postcall is provided to bind + lifetimes after invocation. Also, if a C++ exception is thrown after + with_custodian_and_ward<>::precall but before the + underlying C++ object actually stores a pointer, the lifetime of the + custodian and ward objects will be artificially bound together, so one + might choose with_custodian_and_ward_postcall instead, + depending on the semantics of the function being wrapped. +

+

+ Please note that this is not the appropriate tool to use when + wrapping functions which transfer ownership of a raw pointer + across the function-call boundary. Please see the FAQ if you want to do that. +

+

+ Classes +

+

+ Class template + with_custodian_and_ward +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ with_custodian_and_ward template parameters +
+ Parameter + + Requirements + + Description + + Default +
+ custodian + + A positive compile-time constant of type std::size_t. + + The 1-based index of the parameter which is the dependency in the + lifetime relationship to be established. If used to wrap a member + function, parameter 1 is the target object (*this). + Note that if the target Python object type doesn't support weak + references, a Python TypeError exception will be + raised when the C++ object being wrapped is called. +
+ ward + + A positive compile-time constant of type std::size_t. + + The 1-based index of the parameter which is the dependent in the + lifetime relationship to be established. If used to wrap a member + function, parameter 1 is the target object (*this). +
+ Base + + A model of CallPolicies + + Used for policy + composition. + + default_call_policies +
+

+ Class template + with_custodian_and_ward synopsis +

+
+namespace boost { namespace python
+{
+   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
+   struct with_custodian_and_ward : Base
+   {
+      static bool precall(PyObject* args);
+   };
+}}
+
+

+ Class + with_custodian_and_ward static functions +

+
+bool precall(PyObject* args);
+
+
+
+ Requires: PyTuple_Check(args) + != 0 +
+
+ Effects: Makes the lifetime of the argument indicated by + ward dependent on the lifetime of the argument indicated + by custodian. +
+
+ Returns: false and PyErr_Occurred() != 0 + upon failure, true otherwise. +
+
+

+ Class template + with_custodian_and_ward_postcall +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ with_custodian_and_ward_postcall template + parameters +
+ Parameter + + Requirements + + Description + + Default +
+ custodian + + A compile-time constant of type std::size_t. + + The index of the parameter which is the dependency in the lifetime + relationship to be established. Zero indicates the result object; 1 + indicates the first argument. If used to wrap a member function, + parameter 1 is the target object (*this). Note that if + the target Python object type doesn't support weak references, a + Python TypeError exception will be raised when the C++ + object being wrapped is called. +
+ ward + + A compile-time constant of type std::size_t. + + The index of the parameter which is the dependent in the lifetime + relationship to be established. Zero indicates the result object; 1 + indicates the first argument. If used to wrap a member function, + parameter 1 is the target object (*this). +
+ Base + + A model of CallPolicies + + Used for policy + composition. + + default_call_policies +
+

+ Class + template with_custodian_and_ward_postcall synopsis +

+
+namespace boost { namespace python
+{
+   template <std::size_t custodian, std::size_t ward, class Base = default_call_policies>
+   struct with_custodian_and_ward_postcall : Base
+   {
+      static PyObject* postcall(PyObject* args, PyObject* result);
+   };
+}}
+
+

+ Class + with_custodian_and_ward_postcall static functions +

+
+PyObject* postcall(PyObject* args, PyObject* result);
+
+
+
+ Requires: PyTuple_Check(args) + != 0, result != 0. +
+
+ Effects: Makes the lifetime of the object indicated by + ward dependent on the lifetime of the object indicated + by custodian. +
+
+ Returns: 0 and PyErr_Occurred() != 0 + upon failure, true otherwise. +
+
+

+ Example +

The following example shows how + with_custodian_and_ward_postcall is used by the library to + implement return_internal_reference + +
+template <std::size_t owner_arg = 1, class Base = default_call_policies>
+struct return_internal_reference
+    : with_custodian_and_ward_postcall<0, owner_arg, Base>
+{
+   typedef reference_existing_object result_converter;
+};
+
+

+ Revised + + 13 November, 2002 + +

+

+ © Copyright Dave + Abrahams 2002. +

+ + diff --git a/libs/python/doc/v2/wrapper.html b/libs/python/doc/v2/wrapper.html new file mode 100644 index 0000000000..06239754a9 --- /dev/null +++ b/libs/python/doc/v2/wrapper.html @@ -0,0 +1,238 @@ + + + + + + Boost.Python - <wrapper.hpp> + + + +
+

+

+ +
+

Boost.Python

+ +

Header <wrapper.hpp>

+
+
+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class template + override
+ +
+
+
Class + override synopsis
+ +
Class + override observer functions
+
+
+ +
Class template + wrapper
+ +
+
+
Class wrapper + synopsis
+ +
Class + wrapper observer functions
+
+
+
+
+ +
Example(s)
+
+
+ +

Introduction

+ +

To wrap a class T such that its virtual functions can be + "overridden in Python"—so that the corresponding method of a Python + derived class will be called when the virtual function is invoked from + C++—you must create a C++ wrapper class derived from ``T`` that + overrides those virtual functions so that they call into Python. This + header contains classes that can be used to make that job easier.

+ +

Classes

+ +

Class override

+ +

Encapsulates a Python override of a C++ virtual function. An + override object either holds a callable Python object or + None.

+ +

Class override + synopsis

+
+namespace boost
+{
+  class override : object
+  {
+   public:
+      unspecified operator() const;
+      template <class A0>
+      unspecified operator(A0) const;
+      template <class A0, class A1>
+      unspecified operator(A0, A1) const;
+      ...
+      template <class A0, class A1, ...class An>
+      unspecified operator(A0, A1, ...An) const;
+  };
+};
+
+ +

Class override + observer functions

+
+unspecified operator() const;
+template <class A0>
+unspecified operator(A0) const;
+template <class A0, class A1>
+unspecified operator(A0, A1) const;
+...
+template <class A0, class A1, ...class An>
+unspecified operator(A0, A1, ...An) const;
+
+ +
+
Effects: If *this holds a callable Python + object, it is invoked with the specified arguments in the manner + specified here. Otherwise, throws error_already_set + .
+ +
Returns: An object of unspecified type that holds the Python + result of the invocation and, when converted to a C++ type + R, attempts to convert that result object to + R. If that conversion fails, throws error_already_set + .
+
+ +

Class template wrapper

+ +

Deriving your wrapper class from both ``T`` and + ``wrapper<T> makes writing that derived class easier.

+ +

Class template + wrapper synopsis

+
+namespace boost
+{
+  class wrapper
+  {
+   protected:
+      override get_override(char const* name) const;
+  };
+};
+
+ +

Class wrapper + observer functions

+
+override get_override(char const* name) const;
+
+ +
+
Requires: name is a ntbs.
+ +
Returns: If *this is the C++ base class + subobject of a Python derived class instance that overrides the named + function, returns an override object that delegates to the + Python override. Otherwise, returns an override object + that holds None.
+
+ +

Example

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/wrapper.hpp>
+#include <boost/python/call.hpp>
+
+using namespace boost::python;
+
+// Class with one pure virtual function
+struct P
+{
+    virtual ~P(){}
+    virtual char const* f() = 0;
+    char const* g() { return "P::g()"; }
+};
+
+struct PCallback : P, wrapper<P>
+{
+    char const* f()
+    {
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
+        return call<char const*>(this->get_override("f").ptr());
+#else 
+        return this->get_override("f")();
+#endif 
+    }
+};
+
+// Class with one non-pure virtual function
+struct A
+{
+    virtual ~A(){}
+    virtual char const* f() { return "A::f()"; }
+};
+
+struct ACallback :  A, wrapper<A>
+{
+    char const* f()
+    {
+        if (override f = this->get_override("f"))
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
+            return call<char const*>(f.ptr());
+#else 
+            return f();
+#endif 
+
+        return A::f();
+    }
+
+    char const* default_f() { return this->A::f(); }
+};
+
+BOOST_PYTHON_MODULE_INIT(polymorphism)
+{
+    class_<PCallback,boost::noncopyable>("P")
+        .def("f", pure_virtual(&P::f))
+        ;
+
+    class_<ACallback,boost::noncopyable>("A")
+        .def("f", &A::f, &ACallback::default_f)
+        ;
+}
+
+ +

Revised + + 31 October, 2004 + + + +

© Copyright Dave + Abrahams 2004 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)

+ -- cgit v1.2.3