From 53d2398e0654b67463c4326b7dc8ba134d925711 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 6 Mar 2001 02:45:39 +0000 Subject: [PATCH 01/23] remove temp files after branching. [SVN r9459] --- example/dvect.cpp | 68 ---------------------------------- example/dvect.h | 32 ---------------- example/ivect.cpp | 68 ---------------------------------- example/ivect.h | 32 ---------------- example/noncopyable.h | 14 ------- example/noncopyable_export.cpp | 23 ------------ example/noncopyable_import.cpp | 41 -------------------- example/tst_dvect.py | 16 -------- example/tst_ivect.py | 16 -------- example/tst_noncopyable.py | 8 ---- 10 files changed, 318 deletions(-) delete mode 100644 example/dvect.cpp delete mode 100644 example/dvect.h delete mode 100644 example/ivect.cpp delete mode 100644 example/ivect.h delete mode 100644 example/noncopyable.h delete mode 100644 example/noncopyable_export.cpp delete mode 100644 example/noncopyable_import.cpp delete mode 100644 example/tst_dvect.py delete mode 100644 example/tst_ivect.py delete mode 100644 example/tst_noncopyable.py diff --git a/example/dvect.cpp b/example/dvect.cpp deleted file mode 100644 index 47f70d3b..00000000 --- a/example/dvect.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "ivect.h" -#include "dvect.h" -#include -namespace python = boost::python; - -namespace { - - vects::ivect dvect_as_ivect(const vects::dvect& dv) - { - vects::ivect iv(dv.size()); - vects::ivect::iterator iviter = iv.begin(); - for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); - return iv; - } - - boost::python::tuple ivect_as_tuple(const vects::ivect& iv) - { - return iv.as_tuple(); - } - - std::auto_ptr auto_ptr_ivect(const vects::dvect& dv) - { - return std::auto_ptr(new vects::ivect(dvect_as_ivect(dv))); - } - - boost::shared_ptr shared_ptr_ivect(const vects::dvect& dv) - { - return boost::shared_ptr(new vects::ivect(dvect_as_ivect(dv))); - } - - boost::python::tuple auto_ptr_ivect_as_tuple(std::auto_ptr& iv) - { - return iv->as_tuple(); - } - - boost::python::tuple shared_ptr_ivect_as_tuple(boost::shared_ptr& iv) - { - return iv->as_tuple(); - } -} - -extern "C" -DL_EXPORT(void) -initdvect() -{ - try - { - python::module_builder this_module("dvect"); - - python::x_class_builder dvect_class(this_module, "dvect"); - - python::import_class_builder ivect_class("ivect", "ivect"); - - dvect_class.def(python::constructor()); - dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); - dvect_class.def(dvect_as_ivect, "as_ivect"); - - this_module.def(ivect_as_tuple, "ivect_as_tuple"); - dvect_class.def(auto_ptr_ivect, "auto_ptr_ivect"); - dvect_class.def(shared_ptr_ivect, "shared_ptr_ivect"); - this_module.def(auto_ptr_ivect_as_tuple, "auto_ptr_ivect_as_tuple"); - this_module.def(shared_ptr_ivect_as_tuple, "shared_ptr_ivect_as_tuple"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/dvect.h b/example/dvect.h deleted file mode 100644 index 8ffe7b50..00000000 --- a/example/dvect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef DVECT_H -#define DVECT_H - -#include -#include - -namespace vects { - - struct dvect : public std::vector - { - dvect() : std::vector() {} - dvect(size_t n) : std::vector(n) {} - dvect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // DVECT_H diff --git a/example/ivect.cpp b/example/ivect.cpp deleted file mode 100644 index dfd90fc9..00000000 --- a/example/ivect.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "ivect.h" -#include "dvect.h" -#include -namespace python = boost::python; - -namespace { - - vects::dvect ivect_as_dvect(const vects::ivect& iv) - { - vects::dvect dv(iv.size()); - vects::dvect::iterator dviter = dv.begin(); - for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); - return dv; - } - - boost::python::tuple dvect_as_tuple(const vects::dvect& dv) - { - return dv.as_tuple(); - } - - std::auto_ptr auto_ptr_dvect(const vects::ivect& iv) - { - return std::auto_ptr(new vects::dvect(ivect_as_dvect(iv))); - } - - boost::shared_ptr shared_ptr_dvect(const vects::ivect& iv) - { - return boost::shared_ptr(new vects::dvect(ivect_as_dvect(iv))); - } - - boost::python::tuple auto_ptr_dvect_as_tuple(std::auto_ptr& dv) - { - return dv->as_tuple(); - } - - boost::python::tuple shared_ptr_dvect_as_tuple(boost::shared_ptr& dv) - { - return dv->as_tuple(); - } -} - -extern "C" -DL_EXPORT(void) -initivect() -{ - try - { - python::module_builder this_module("ivect"); - - python::x_class_builder ivect_class(this_module, "ivect"); - - python::import_class_builder dvect_class("dvect", "dvect"); - - ivect_class.def(python::constructor()); - ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); - ivect_class.def(ivect_as_dvect, "as_dvect"); - - this_module.def(dvect_as_tuple, "dvect_as_tuple"); - ivect_class.def(auto_ptr_dvect, "auto_ptr_dvect"); - ivect_class.def(shared_ptr_dvect, "shared_ptr_dvect"); - this_module.def(auto_ptr_dvect_as_tuple, "auto_ptr_dvect_as_tuple"); - this_module.def(shared_ptr_dvect_as_tuple, "shared_ptr_dvect_as_tuple"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/ivect.h b/example/ivect.h deleted file mode 100644 index a0187307..00000000 --- a/example/ivect.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef IVECT_H -#define IVECT_H - -#include -#include - -namespace vects { - - struct ivect : public std::vector - { - ivect() : std::vector() {} - ivect(size_t n) : std::vector(n) {} - ivect(boost::python::tuple tuple) : std::vector(tuple.size()) - { - std::vector::iterator v_it = begin(); - for (int i = 0; i < tuple.size(); i++) - v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), - boost::python::type()); - } - - boost::python::tuple as_tuple() const - { - boost::python::tuple t(size()); - for (int i = 0; i < size(); i++) - t.set_item(i, - boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); - return t; - } - }; -} - -#endif // IVECT_H diff --git a/example/noncopyable.h b/example/noncopyable.h deleted file mode 100644 index de7b3672..00000000 --- a/example/noncopyable.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NONCOPYABLE_H -#define NONCOPYABLE_H - -class store -{ - private: - store(const store&) { } // Disable the copy constructor. - int number; - public: - store(const int i) : number(i) { } - int recall() const { return number; } -}; - -#endif // NONCOPYABLE_H diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp deleted file mode 100644 index 31cbe7c8..00000000 --- a/example/noncopyable_export.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -namespace python = boost::python; - -#include "noncopyable.h" - -extern "C" -DL_EXPORT(void) -initnoncopyable_export() -{ - try - { - python::module_builder this_module("noncopyable_export"); - - python::xptr_class_builder store_class(this_module, "store"); - - store_class.def(python::constructor()); - store_class.def(&store::recall, "recall"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp deleted file mode 100644 index f2b2c6d0..00000000 --- a/example/noncopyable_import.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -namespace python = boost::python; - -#include "noncopyable.h" - -namespace { // Avoid cluttering the global namespace. - - // A function with store objects as both input and output parameters. - // Because the copy constructor is disabled, we cannot pass a store - // object by value. Instead, we pass a smart pointer. - std::auto_ptr add_stores(const store& s1, const store& s2) - { - int sum = s1.recall() + s2.recall(); - std::auto_ptr ss = std::auto_ptr(new store(sum)); - return ss; - } -} - -extern "C" -DL_EXPORT(void) -initnoncopyable_import() -{ - try - { - python::module_builder this_module("noncopyable_import"); - - python::import_class_builder - dvect_class("noncopyable_export", "store"); - - // Imagine all the additional classes with member functions - // that have store objects as input and output parameters. - // Lots and lots of them. - // However, to keep this example simple, we only define a - // module-level function. - this_module.def(add_stores, "add_stores"); - } - catch(...) - { - python::handle_exception(); // Deal with the exception for Python - } -} diff --git a/example/tst_dvect.py b/example/tst_dvect.py deleted file mode 100644 index 563f0ad5..00000000 --- a/example/tst_dvect.py +++ /dev/null @@ -1,16 +0,0 @@ -import dvect -print dvect.dvect.__converters__ -dv = dvect.dvect((1,2,3,4,5)) -print dv -print dv.as_tuple() -iv = dv.as_ivect() -print iv -print iv.as_tuple() -print dvect.ivect_as_tuple(iv) -aiv = dv.auto_ptr_ivect() -print aiv -siv = dv.shared_ptr_ivect() -print dvect.auto_ptr_ivect_as_tuple(aiv) -print dvect.ivect_as_tuple(aiv) -print dvect.shared_ptr_ivect_as_tuple(siv) -print dvect.ivect_as_tuple(siv) diff --git a/example/tst_ivect.py b/example/tst_ivect.py deleted file mode 100644 index 58bc323f..00000000 --- a/example/tst_ivect.py +++ /dev/null @@ -1,16 +0,0 @@ -import ivect -print ivect.ivect.__converters__ -iv = ivect.ivect((1,2,3,4,5)) -print iv -print iv.as_tuple() -dv = iv.as_dvect() -print dv -print dv.as_tuple() -print ivect.dvect_as_tuple(dv) -adv = iv.auto_ptr_dvect() -print adv -sdv = iv.shared_ptr_dvect() -print ivect.auto_ptr_dvect_as_tuple(adv) -print ivect.dvect_as_tuple(adv) -print ivect.shared_ptr_dvect_as_tuple(sdv) -print ivect.dvect_as_tuple(sdv) diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py deleted file mode 100644 index 913df039..00000000 --- a/example/tst_noncopyable.py +++ /dev/null @@ -1,8 +0,0 @@ -import noncopyable_export -import noncopyable_import -s1 = noncopyable_export.store(1) -print s1.recall() -s2 = noncopyable_export.store(2) -print s2.recall() -s3 = noncopyable_import.add_stores(s1, s2) -print s3.recall() From 116b3db1d1b6ebbaab7aca99401b6a8dd332d613 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 6 Mar 2001 20:55:09 +0000 Subject: [PATCH 02/23] Fixed typo in use of "PYTHON_LIB" [SVN r9467] --- build/como.mak | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/como.mak b/build/como.mak index c6f340a5..581eefea 100644 --- a/build/como.mak +++ b/build/como.mak @@ -1,5 +1,7 @@ # Revision History: +# 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams) # 04 Mar 01 Changed library name to libboost_python.a (David Abrahams) + LIBSRC = \ classes.cpp \ conversions.cpp \ @@ -33,7 +35,7 @@ endif [ -s $@ ] || rm -f $@ example1: example1.o libboost_python.a - como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYHTON_LIB) example1.o -L. -lboost_python + como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYTHON_LIB) example1.o -L. -lboost_python python ../example/test_example1.py example1.o: ../example/example1.cpp From 617bcdac9f81d1486c585158b9c7694f2f5c48fd Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:39:31 +0000 Subject: [PATCH 03/23] Major doc updates [SVN r9470] --- doc/building.html | 195 +++++++++++++++++++++++++++++-------- doc/comparisons.html | 61 +++++++----- doc/enums.html | 43 +++++--- doc/example1.html | 112 ++++++--------------- doc/exporting_classes.html | 144 +++++++++++++++++++++++++++ doc/extending.html | 4 +- doc/index.html | 91 +++++++++-------- doc/inheritance.html | 26 ++--- doc/overloading.html | 6 +- doc/overriding.html | 98 +++++++++++-------- doc/pickle.html | 28 +++--- doc/pointers.html | 4 +- doc/special.html | 28 +++--- doc/under-the-hood.html | 4 +- 14 files changed, 551 insertions(+), 293 deletions(-) create mode 100644 doc/exporting_classes.html diff --git a/doc/building.html b/doc/building.html index 4ac2343c..6627bbe8 100644 --- a/doc/building.html +++ b/doc/building.html @@ -1,44 +1,157 @@ - - - Building an Extension Module - + + + + + Building an Extension Module +
-

- c++boost.gif (8819 bytes)Building an Extension Module -

-

- Right now, the only supported configuration is one in which the BPL - source files are statically linked with the source for your extension - module. You may first build them into a library and link it with your - extension module source, but the effect is the same as compiling all - the source files together. Some users have successfully built the - sources into a shared library, and support for a shared library - build is planned, but not yet implemented. The BPL source files are: -

-
-extclass.cpp
-functions.cpp
-init_function.cpp
-module.cpp
-newtypes.cpp
-objects.cpp
-py.cpp
-subclass.cpp
-         
-
-

- Next: Enums - Previous: A Peek Under the Hood - Up: Top -

- © Copyright David Abrahams 2000. 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. -

- Updated: Nov 26, 2000 +

c++boost.gif (8819 bytes)Building an + Extension Module

+ +

The build process for Boost is currently undergoing some evolution, + and, it is to be hoped, improvement. The following facts may help: + +

    +
  • + Makefiles for various platforms reside in the Boost subdirectory + libs/python/build: + +
      +
    • como.mak (Comeau C++ on Linux) + +
    • linux_gcc.mak (GCC on + Linux/Unix) + +
    • gcc.mak (older makefile for GCC + on Linux/Unix. Deprecated.) + +
    • mingw32.mak + (highly-specialized makefile for mingw32 (Win32-targeted) GCC. Read + the header comment). + +
    • tru64_cxx.mak (Compaq + Alpha). +
    +
    + +
  • + A project workspace for Microsoft Visual Studio is provided at libs/python/build/build.dsw. The + include paths for this project may need to be changed for your + installation. They currently assume that python has been installed at + c:\tools\python. Three configurations of all targets are + supported: + +
      +
    • Release (optimization, -DNDEBUG) + +
    • Debug (no optimization -D_DEBUG) + +
    • DebugPython (no optimization, -D_DEBUG + -DBOOST_DEBUG_PYTHON) +
    + +

    When extension modules are built with Visual C++ using + -D_DEBUG, Python defaults to force linking with a + special debugging version of the Python DLL. Since this debug DLL + isn't supplied with the default Python installation for Windows, + Boost.Python uses boost/python/detail/wrap_python.hpp + to temporarily undefine _DEBUG when Python.h is + #included. + +

    If you want the extra runtime checks available with the debugging + version of the library, #define BOOST_DEBUG_PYTHON to + re-enable library forcing, and link with the DebugPython version of + boost_python.lib. You'll need to get the debugging version + of the Python executable (python_d.exe) and DLL + (python20_d.dll or python15_d.dll). The Python + sources include project files for building these. If you download them, change the name of the + top-level directory to src, and install it under + c:\tools\python, the workspace supplied by Boost.Python will + be able to use it without modification. Just open + c:\tools\python\src\pcbuild\pcbuild.dsw and invoke "build + all" to generate all the debugging targets. + +

    If you do not #define BOOST_DEBUG_PYTHON, be sure that + any source files #include <boost/python/detail/wrap_python.hpp> + instead of the usual Python.h, or you will have link + incompatibilities.
    +
    + + +

  • + The makefiles and Visual Studio project can all build at least the + following: + +
      +
    • The boost_python library for static linking with your + extension module. On the various Unices, this library will be + called libboost_python.a. On Win32 platforms, the library + will be called boost_python.lib. + +
    • A comprehensive test of Boost.Python features. This test builds + a Boost.Python extension module, then runs Python to import the + module, and runs a series of tests on it using doctest. Source code for the module + and tests is available in the Boost subdirectory + libs/python/test.
      + + +
    • Various examples from the Boost subdirectory + libs/python/example. Which examples are built currently + depends on the platform. The most up-to-date examples are + getting_startedn.cpp from Ralf W. + Grosse-Kunstleve. All these examples include a doctest modeled + on the comprehensive test above.
      +
      + +
    + +
  • + If your platform isn't directly supported, you can build a static + library from the following source files (in the Boost subdirectory + libs/python/src), or compile them directly and link the + resulting objects into your extension module: + + +
+ +

Next: Wrapping Enums Previous: A Peek Under the Hood Up: Top + +

© Copyright David Abrahams 2000. 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. + +

Updated: Mar 6, 2001

diff --git a/doc/comparisons.html b/doc/comparisons.html index 336220fb..6f082d51 100644 --- a/doc/comparisons.html +++ b/doc/comparisons.html @@ -6,13 +6,14 @@

c++boost.gif (8819 bytes)Comparisons with + src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">
+ Comparisons with Other Systems

CXX

- Like BPL, CXX attempts to + Like Boost.Python, CXX attempts to provide a C++-oriented interface to Python. In most cases, as with the boost library, it relieves the user from worrying about reference-counts. Both libraries automatically convert thrown C++ @@ -40,9 +41,15 @@

As far as I can tell, CXX enables one to write what is essentially idiomatic Python code in C++, manipulating Python objects through the - same fully-generic interfaces we use in Python. While you're hardly programming directly to the ``bare - metal'' with CXX, it basically presents a ``C++-ized'' - version of the Python 'C' API. + same fully-generic interfaces we use in Python. While you're hardly + programming directly to the ``bare metal'' with CXX, it basically + presents a ``C++-ized'' version of the Python 'C' API. Some fraction of + that capability is available in Boost.Python through boost/python/objects.hpp, + which provides C++ objects corresponding to Python lists, tuples, + strings, and dictionaries, and through boost/python/callback.hpp, + which allows you to call back into python with C++ arguments.

Paul F. Dubois, the original @@ -65,7 +72,7 @@ that.''
-Paul Dubois languages. Swig relies on a parser to read your source code and produce additional source code files which can be compiled into a Python (or Perl or Tcl) extension module. It has been successfully used to create - many Python extension modules. Like BPL, SWIG is trying to allow an + many Python extension modules. Like Boost.Python, SWIG is trying to allow an existing interface to be wrapped with little or no change to the existing code. The documentation says ``SWIG parses a form of ANSI C syntax that has been extended with a number of special directives. As a @@ -78,15 +85,15 @@ that.''
-Paul Dubois couldnt handle templates, didnt do func overloading properly etc. For ANSI C libraries this was fine. But for usual C++ code this was a problem. Simple things work. But for anything very complicated (or - realistic), one had to write code by hand. I believe BPL doesn't have + realistic), one had to write code by hand. I believe Boost.Python doesn't have this problem[sic]... IMHO overloaded functions are very important to wrap correctly.''
-Prabhu Ramachandran

- By contrast, BPL doesn't attempt to parse C++ - the problem is simply + By contrast, Boost.Python doesn't attempt to parse C++ - the problem is simply too complex to do correctly. Technically, one does - write code by hand to use BPL. The goal, however, has been to make + write code by hand to use Boost.Python. The goal, however, has been to make that code nearly as simple as listing the names of the classes and member functions you want to expose in Python. @@ -95,7 +102,7 @@ that.''
-Paul Dubois SIP is a system similar to SWIG, though seemingly more - C++-oriented. The author says that like BPL, SIP supports overriding + C++-oriented. The author says that like Boost.Python, SIP supports overriding extension class member functions in Python subclasses. It appears to have been designed specifically to directly support some features of PyQt/PyKDE, which is its primary client. Documentation is almost @@ -113,7 +120,7 @@ that.''
-Paul Dubois to a wide range of computer languages, including Common Lisp, C++, C, Modula-3, and Python. ILU can parse the ISL to generate a C++ language header file describing the interface, of which the user is expected to - provide an implementation. Unlike BPL, this means that the system + provide an implementation. Unlike Boost.Python, this means that the system imposes implementation details on your C++ code at the deepest level. It is worth noting that some of the C++ names generated by ILU are supposed to be reserved to the C++ implementation. It is unclear from the @@ -148,7 +155,7 @@ an inheritance relationship?

Zope ExtensionClasses

- ExtensionClasses in Zope use the same underlying mechanism as BPL + ExtensionClasses in Zope use the same underlying mechanism as Boost.Python to support subclassing of extension types in Python, including multiple-inheritance. Both systems support pickling/unpickling of extension class instances in very similar ways. Both systems rely on the @@ -158,31 +165,35 @@ an inheritance relationship?

The major differences are:

    +
  • Zope is entirely 'C' language-based. It doesn't require a C++ + compiler, so it's much more portable than Boost.Python, which stresses + the limits of even some modern C++ implementations. +
  • - BPL lifts the burden on the user to parse and convert function + Boost.Python lifts the burden on the user to parse and convert function argument types. Zope provides no such facility.
  • - BPL lifts the burden on the user to maintain Python + Boost.Python lifts the burden on the user to maintain Python reference-counts.
  • - BPL supports function overloading; Zope does not. + Boost.Python supports function overloading; Zope does not.
  • - BPL supplies a simple mechanism for exposing read-only and + Boost.Python supplies a simple mechanism for exposing read-only and read/write access to data members of the wrapped C++ type as Python attributes.
  • Writing a Zope ExtensionClass is significantly more complex than - exposing a C++ class to python using BPL (mostly a summary of the + exposing a C++ class to python using Boost.Python (mostly a summary of the previous 4 items). A Zope Example illustrates the differences.
  • Zope's ExtensionClasses are specifically motivated by ``the need for a - C-based persistence mechanism''. BPL's are motivated by the desire + C-based persistence mechanism''. Boost.Python's are motivated by the desire to simply reflect a C++ API into Python with as little modification as possible.
  • - The following Zope restriction does not apply to BPL: ``At most one + The following Zope restriction does not apply to Boost.Python: ``At most one base extension direct or indirect super class may define C data members. If an extension subclass inherits from multiple base extension classes, then all but one must be mix-in classes that @@ -191,21 +202,21 @@ an inheritance relationship? Zope requires use of the somewhat funky inheritedAttribute (search for ``inheritedAttribute'' on this page) - method to access base class methods. In BPL, base class methods can + method to access base class methods. In Boost.Python, base class methods can be accessed in the usual way by writing ``BaseClass.method''.
  • Zope supplies some creative but esoteric idioms such as - Acquisition. No specific support for this is built into BPL. + Acquisition. No specific support for this is built into Boost.Python.
  • Zope's ComputedAttribute support is designed to be used from Python. The analogous feature of - BPL can be used from C++ or Python. The feature is arguably - easier to use in BPL. + Boost.Python can be used from C++ or Python. The feature is arguably + easier to use in Boost.Python.

- Next: A Simple Example Using BPL + Next: A Simple Example Using Boost.Python Previous: A Brief Introduction to writing Python Extension Modules Up: Top

@@ -215,6 +226,6 @@ an inheritance relationship? express or implied warranty, and with no claim as to its suitability for any purpose.

- Updated: Nov 26, 2000 + Updated: Mar 6, 2001

diff --git a/doc/enums.html b/doc/enums.html index 04138ff1..32d61447 100644 --- a/doc/enums.html +++ b/doc/enums.html @@ -6,7 +6,8 @@

c++boost.gif (8819 bytes)Wrapping enums + src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">
+ Wrapping enums

Because there is in general no way to deduce that a value of arbitrary type T @@ -17,24 +18,39 @@ enums). Once you have done that, you can write some simple from_python() and to_python() functions.

If you are satisfied with a Python int as a way to represent your enum -values, we provide a shorthand for these functions. You just need to -instantiate boost::python::enum_as_int_converters<EnumType> where +values, we provide a shorthand for these functions. You just need to cause +boost::python::enum_as_int_converters<EnumType> to be +instantiated, where EnumType is your enumerated type. There are two convenient ways to do this:

    -
  1. +
  2. Explicit instantiation: + +
    +  template class boost::python::enum_as_int_converters<my_enum>;
    +
    + +Some buggy C++ implementations require a class to be instantiated in the same +namespace in which it is defined. In that case, the simple incantation above becomes: + +
        ...
     } // close my_namespace
    +
     // drop into namespace python and explicitly instantiate
    -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
    -  template class enum_as_int_converters;
    -BOOST_PYTHON_END_CONVERSION_NAMESPACE
    +namespace boost { namespace python {
    +  template class enum_as_int_converters<my_enum_type>;
    +}} // namespace boost::python
    +
     namespace my_namespace { // re-open my_namespace
        ...
     
    -
  3. +
    +
    +
  4. If you have such an implementation, you may find this technique more convenient +
     // instantiate as base class in any namespace
     struct EnumTypeConverters
         : boost::python::enum_as_int_converters<EnumType>
    @@ -71,7 +87,8 @@ BOOST_PYTHON_END_CONVERSION_NAMESPACE
      long type.
     
     You may also want to add a bunch of lines like this to your module
    -initialization:
    +initialization. These bind the corresponding enum values to the appropriate
    +names so they can be used from Python:
     
     
     mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
    @@ -83,12 +100,12 @@ You can also add these to an extension class definition, if your enum happens to
     be local to a class and you want the analogous interface in Python:
     
     
    -my_class.add(boost::python::to_python(enum_value_1), "enum_value_1");
    -my_class.add(boost::python::to_python(enum_value_2), "enum_value_2");
    +my_class_builder.add(boost::python::to_python(enum_value_1), "enum_value_1");
    +my_class_builder.add(boost::python::to_python(enum_value_2), "enum_value_2");
     ...
     

    - Next: Pointers + Next: Pointers and Smart Pointers Previous: Building an Extension Module Up: Top

    @@ -98,6 +115,6 @@ my_class.add(boost::python::to_python(enum_value_2), "enum_value_2"); is'' without express or implied warranty, and with no claim as to its suitability for any purpose.

    - Updated: Nov 26, 2000 + Updated: Mar 6, 2001

diff --git a/doc/example1.html b/doc/example1.html index 655f3d6a..402cc7a6 100644 --- a/doc/example1.html +++ b/doc/example1.html @@ -18,104 +18,56 @@
 #include <string>
 
-namespace hello {
-  class world
-  {
-   public:
-      world(int);
-      ~world();
-      std::string greet() const { return "hi, world"; }
-    ...
-  };
-  std::size_t length(const world& x) { return std::strlen(x.greet()); }
+namespace { // Avoid cluttering the global namespace.
+
+  // A couple of simple C++ functions that we want to expose to Python.
+  std::string greet() { return "hello, world"; }
+  int square(int number) { return number * number; }
 }
 
 

- Here is the C++ code for a python module called hello - which exposes the API using: + Here is the C++ code for a python module called getting_started1 + which exposes the API.

 #include <boost/python/class_builder.hpp>
-// Python requires an exported function called init<module-name> in every
-// extension module. This is where we build the module contents.
-extern "C"
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-void inithello()
+namespace python = boost::python;
+
+BOOST_PYTHON_MODULE_INIT(getting_started1)
 {
-    try
-    {
-       // create an object representing this extension module
-       boost::python::module_builder m("hello");
-       // Create the Python type object for our extension class
-       boost::python::class_builder<hello::world> world_class(m, "world");
-       // Add the __init__ function
-       world_class.def(boost::python::constructor<int>());
-       // Add a regular member function
-       world_class.def(&hello::world::get, "get");
-       // Add a regular function to the module
-       m.def(hello::length, "length");
-    }
-    catch(...)
-    {
-       boost::python::handle_exception();    // Deal with the exception for Python
-    }
+  try
+  {
+    // Create an object representing this extension module.
+    python::module_builder this_module("getting_started1");
+
+    // Add regular functions to the module.
+    this_module.def(greet, "greet");
+    this_module.def(square, "square");
+  }
+  catch(...)
+  {
+    python::handle_exception(); // Deal with the exception for Python
+  }
 }
-// Win32 DLL boilerplate
-#if defined(_WIN32)
-#include <windows.h>
-extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
-{
-    return 1;
-}
-#endif // _WIN32
 

That's it! If we build this shared library and put it on our - PYTHONPATH we can now access our C++ class and function from + PYTHONPATH we can now access our C++ functions from Python.

->>> import hello
->>> hi_world = hello.world(3)
->>> hi_world.greet()
-'hi, world'
->>> hello.length(hi_world)
-9
+>>> import getting_started1
+>>> print getting_started1.greet()
+hello, world
+>>> number = 11
+>>> print number, '*', number, '=', getting_started1.square(number)
+11 * 11 = 121
 
-

- We can even make a subclass of hello.world: -

-
->>> class my_subclass(hello.world):
-...     def greet(self):
-...         return 'hello, world'
-...
->>> y = my_subclass(4)
->>> y.greet()
-'hello, world'
-
-
-

- Pretty cool! You can't do that with an ordinary Python extension type! -

-
->>> hello.length(y)
-9
-
-
-

- Of course, you may now have a slightly empty feeling in the pit of - your little pythonic stomach. Perhaps you feel your subclass deserves - to have a length() of 12? If so, read on... -

- Next: Overridable virtual functions + Next: Exporting Classes Previous: Comparisons with other systems Up: Top

@@ -125,6 +77,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) express or implied warranty, and with no claim as to its suitability for any purpose.

- Updated: Nov 26, 2000 + Updated: Mar 6, 2000 diff --git a/doc/exporting_classes.html b/doc/exporting_classes.html new file mode 100644 index 00000000..e5932e70 --- /dev/null +++ b/doc/exporting_classes.html @@ -0,0 +1,144 @@ + + + Exporting Classes + +

+

+ + +

+

+ Exporting Classes +

+

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

+#include <iostream>
+#include <string>
+
+namespace { // Avoid cluttering the global namespace.
+
+  // A friendly class.
+  class hello
+  {
+    public:
+      hello(const std::string& country) { this->country = country; }
+      std::string greet() const { return "Hello from " + country; }
+    private:
+      std::string country;
+  };
+
+  // A function taking a hello object as an argument.
+  std::string invite(const hello& w) {
+    return w.greet() + "! Please come soon!";
+  }
+}
+
+

+ To expose the class, we use a class_builder in addition to the + module_builder from the previous example. Class member functions + are exposed by using the def() member function on the + class_builder: +

+#include <boost/python/class_builder.hpp>
+namespace python = boost::python;
+
+BOOST_PYTHON_MODULE_INIT(getting_started2)
+{
+  try
+  {
+    // Create an object representing this extension module.
+    python::module_builder this_module("getting_started2");
+
+    // Create the Python type object for our extension class.
+    python::class_builder<hello> hello_class(this_module, "hello");
+
+    // Add the __init__ function.
+    hello_class.def(python::constructor<std::string>());
+    // Add a regular member function.
+    hello_class.def(&hello::greet, "greet");
+
+    // Add invite() as a regular function to the module.
+    this_module.def(invite, "invite");
+
+    // Even better, invite() can also be made a member of hello_class!!!
+    hello_class.def(invite, "invite");
+  }
+  catch(...)
+  {
+    python::handle_exception(); // Deal with the exception for Python
+  }
+}
+
+

+Now we can use the class normally from Python: + +

+>>> from getting_started2 import *
+>>> hi = hello('California')
+>>> hi.greet()
+'Hello from California'
+>>> invite(hi)
+'Hello from California! Please come soon!'
+>>> hi.invite()
+'Hello from California! Please come soon!'
+
+ +Notes:
    +
  • We expose the class' constructor by calling def() on the + class_builder with an argument whose type is + constructor<params>, where params + matches the list of constructor argument types: + + +
  • Regular member functions are defined by calling def() with a + member function pointer and its Python name: + +
  • Any function added to a class whose initial argument matches the class (or +any base) will act like a member function in Python. +
+

+ We can even make a subclass of hello.world: + +

+>>> class wordy(hello):
+...     def greet(self):
+...         return hello.greet(self) + ', where the weather is fine'
+...
+>>> hi2 = wordy('Florida')
+>>> hi2.greet()
+'Hello from Florida, where the weather is fine'
+>>> invite(hi2)
+'Hello from Florida! Please come soon!'
+
+

+ Pretty cool! You can't do that with an ordinary Python extension type! + + Of course, you may now have a slightly empty feeling in the pit of + your little pythonic stomach. Perhaps you wanted to see the following + wordy invitation: + +

+'Hello from Florida, where the weather is fine! Please come soon!'
+
+ + After all, invite calls hello::greet(), and you + reimplemented that in your Python subclass, wordy. If so, read on... + +

+ Next: Overridable virtual functions + Previous: A Simple Example Up: + Top +

+ © Copyright David Abrahams 2000. 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. +

+ Updated: Mar 6, 2001 +

+ diff --git a/doc/extending.html b/doc/extending.html index c4a3a5e4..8839ab43 100644 --- a/doc/extending.html +++ b/doc/extending.html @@ -56,10 +56,10 @@ sublcassing the extension type. Aside from being tedious, it's not really the same as having a true class, because there's no way for the user to override a method of the extension type which is called from the - extension module. BPL solves this problem by taking advantage of Python's metaclass feature to provide objects which look, walk, and hiss almost exactly - like regular Python classes. BPL classes are actually cleaner than + like regular Python classes. Boost.Python classes are actually cleaner than Python classes in some subtle ways; a more detailed discussion will follow (someday).

Next: Comparisons with Other Systems Up: - The Boost Python Library (BPL) + The Boost Python Library (Boost.Python)

c++boost.gif (8819 bytes)The Boost Python Library (BPL) + align="center" height="86">
The Boost Python Library (Boost.Python)

Synopsis

@@ -15,9 +15,9 @@ href="http://www.python.org">Python
such that the Python interface is very similar to the C++ interface. It is designed to be minimally intrusive on your C++ design. In most cases, you should not have to alter - your C++ classes in any way in order to use them with BPL. The system + your C++ classes in any way in order to use them with Boost.Python. The system should simply ``reflect'' your C++ classes and functions into - Python. The major features of BPL include support for: + Python. The major features of Boost.Python include support for:
  • Subclassing extension types in Python
  • Overriding virtual functions in Python @@ -28,9 +28,27 @@ among others.

    Supported Platforms

    -

    BPL has been tested in the following configurations: +

    Boost.Python is known to have been tested in the following configurations:

      +
    • Against Python 2.0 using the following compiler/library combinations: + +
    • Against Python 1.5.2 using the following compiler/library:
        @@ -52,24 +70,17 @@ among others. href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve]
      • An upcoming release of Metrowerks CodeWarrior - Pro6 for Windows (the first release has a bug that's fatal to BPL) + Pro6 for Windows (the first release has a bug that's fatal to Boost.Python)
      -
      -
    • Against Python 2.0 using the following compiler/library combinations: -

    Credits

    • David Abrahams originated - and wrote the library. + and wrote most of the library, and continues to coordinate development.
    • Ullrich Koethe - had independently developed a similar system. When he discovered BPL, + had independently developed a similar system. When he discovered Boost.Python, 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 @@ -78,16 +89,22 @@ among others. Python and C++, and has designed an extremely easy-to-use way of exposing numeric operators, including a way to avoid explicit coercion by means of overloading. + +
    • Ralf W. + Grosse-Kunstleve contributed pickle support + and numerous other small improvements. He's working on a way to allow + types exported by multiple modules to interact.
    • The members of the boost mailing list and the Python community supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans, - Anton Gluck, Ralf W. Grosse-Kunstleve, Chuck Ingold, Prabhu Ramachandran, - and Barry Scott took the brave step of trying to use BPL while it was - still in early stages of development. + Anton Gluck, Chuck Ingold, Prabhu Ramachandran,n and Barry Scott took the + brave step of trying to use Boost.Python while it was still in early + stages of development. -
    • The development of BPL wouldn't have been - possible without the generous support of Dragon Systems/Lernout and - Hauspie, Inc who supported its development as an open-source project. +
    • The development of Boost.Python wouldn't have been possible without + the generous support of Dragon + Systems/Lernout and Hauspie, Inc who supported its development as an + open-source project.

    Table of Contents

    @@ -96,11 +113,13 @@ among others.
  • A Brief Introduction to writing Python extension modules -
  • Comparisons between BPL and other +
  • Comparisons between Boost.Python and other systems for extending Python
  • A Simple Example +
  • Exporting Classes +
  • Overridable Virtual Functions
  • Function Overloading @@ -113,33 +132,19 @@ among others.
  • Building an Extension Module -
  • Advanced Topics +
  • Pickle Support -
      -
    1. Pickle Support +
    2. Wrapping Enums -
    3. class_builder<> +
    4. Pointers and Smart Pointers -
    5. enums - -
    6. References - -
    7. Pointers and Smart Pointers - -
    8. Built-in Python Types - -
    9. Other Extension Types - -
    10. Templates - -
    11. Internal Data Structures -
    +
  • Internal Data Structures

    Documentation is a major ongoing project; assistance is greatly - appreciated! In the meantime, useful examples of every BPL feature should + appreciated! In the meantime, useful examples of every Boost.Python feature should be evident in the regression test files test/comprehensive.[py/hpp/the boost mailing list.

    - © Copyright David Abrahams 2000. Permission to copy, use, modify, + © Copyright David Abrahams 2001. 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.

    - Updated: Nov 26, 2000 + Updated: Mar 6, 2001 diff --git a/doc/inheritance.html b/doc/inheritance.html index d11899c8..cd95c744 100644 --- a/doc/inheritance.html +++ b/doc/inheritance.html @@ -12,10 +12,10 @@

    Inheritance in Python

    - BPL extension classes support single and multiple-inheritance in + Boost.Python extension classes support single and multiple-inheritance in Python, just like regular Python classes. You can arbitrarily mix built-in Python classes with extension classes in a derived class' - tuple of bases. Whenever a BPL extension class is among the bases for a + tuple of bases. Whenever a Boost.Python extension class is among the bases for a new class in Python, the result is an extension class:

    @@ -37,7 +37,7 @@
     
     

    Reflecting C++ Inheritance Relationships

    - BPL also allows us to represent C++ inheritance relationships so that + Boost.Python also allows us to represent C++ inheritance relationships so that wrapped derived classes may be passed where values, pointers, or references to a base class are expected as arguments. The declare_base member function of @@ -76,11 +76,7 @@ int get_derived_x(const Derived& d) { // namespace alias for code brevity namespace python = boost::python; -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initmy_module() +BOOST_PYTHON_MODULE_INIT(my_module) {     try     { @@ -115,11 +111,19 @@ void initmy_module() >>> derived = Derived() >>> get_name(base) 'Base' -

    objects of wrapped class Derived may be passed where Base is expected
    +
    +
    +objects of wrapped class Derived may be passed where Base is expected +
    +
     >>> get_name(derived) 
     'Derived'
    -
    objects of wrapped class Derived can be passed where Derived is -expected but where type information has been lost.
    +
    +
    +objects of wrapped class Derived can be passed where Derived is +expected but where type information has been lost. +
    +
     >>> get_derived_x(derived_as_base()) 
     -1
     
    diff --git a/doc/overloading.html b/doc/overloading.html index 6979efd0..242e023f 100644 --- a/doc/overloading.html +++ b/doc/overloading.html @@ -29,7 +29,7 @@ private: }; ... -void initoverload_demo() +BOOST_PYTHON_MODULE_INIT(overload_demo) {     try     { @@ -144,12 +144,12 @@ namespace scope as Python member functions. Previous: Overridable Virtual Functions Up: Top

    - © Copyright David Abrahams 2000. Permission to copy, use, modify, + © Copyright David Abrahams 2001. 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.

    - Updated: Nov 26, 2000 + Updated: Mar 6, 2001 diff --git a/doc/overriding.html b/doc/overriding.html index ae629580..7b28add1 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -9,7 +9,7 @@

    Overridable Virtual Functions

    - In the previous example we exposed a simple + In the previous example we exposed a simple C++ class in Python and showed that we could write a subclass. We even redefined one of the functions in our derived class. Now we will learn how to make the function behave virtually when called from C++. @@ -17,16 +17,17 @@

    Example

    -

    In this example, it is assumed that world::greet() is a virtual +

    In this example, it is assumed that hello::greet() is a virtual member function:

    -class world
    +class hello
     {
      public:
    -    world(int);
    -    virtual ~world();
    -    virtual std::string greet() const { return "hi, world"; }
    +    hello(const std::string& country) { this->country = country; }
    +    virtual std::string greet() const { return "Hello from " + country; }
    +    virtual ~hello(); // Good practice 
    +    ...
     };
     
    @@ -37,21 +38,28 @@ class world
      -
    1. A PyObject* data member that holds a - reference to the corresponding Python object. +
    2. A PyObject* data member (usually + called self) that holds a pointer to the Python object corresponding + to our C++ hello instance. -
    3. A constructor for each exposed constructor of the - base class which stores an additional initial PyObject* argument - in the data member described above. +
    4. For each exposed constructor of the + base class T, a constructor which takes the same parameters preceded by an initial + PyObject* argument. The initial argument should be stored in the self data + member described above. + +
    5. If the class being wrapped is ever returned by + value from a wrapped function, be sure you do the same for the + T's copy constructor: you'll need a constructor taking arguments + (PyObject*, const T&).
    6. An implementation of each virtual function you may wish to override in Python which uses - boost::python::callback<return-type>::call_method() to call + callback<return-type>::call_method(self, "name", args...) to call the Python override.
    7. For each non-pure virtual function meant to be overridable from Python, a static member function (or a free function) taking - a reference or pointer to the base type as the first parameter and which + a reference or pointer to the T as the first parameter and which forwards any additional parameters neccessary to the default implementation of the virtual function. See also this note if the base class virtual function is private. @@ -59,52 +67,60 @@ class world
    -struct world_callback : world
    +struct hello_callback : hello
     {
    -    world_callback(PyObject* self, int x) // 2
    -        : world(x),
    -          m_self(self) {}
    +    // hello constructor storing initial self_ parameter
    +    hello_callback(PyObject* self_, const std::string& x) // 2
    +        : hello(x), self(self_) {}
     
    -    std::string greet() const // 3
    -        { return boost::python::callback<std::string>::call_method(m_self, "get"); }
    +    // In case hello is returned by-value from a wrapped function
    +    hello_callback(PyObject* self_, const hello& x) // 3
    +        : hello(x), self(self_) {}
     
    -    static std::string default_get(const hello::world& self) const // 4
    -        { return self.world::greet(); }
    +    // Override greet to call back into Python
    +    std::string greet() const // 4
    +        { return boost::python::callback<std::string>::call_method(m_self, "greet"); }
    +
    +    // Supplies the default implementation of greet
    +    static std::string default_greet(const hello& self) const // 5
    +        { return self.hello::greet(); }
      private:
         PyObject* m_self; // 1
     };
     

    - Finally, we add world_callback to the - class_builder<> declaration in our module initialization + Finally, we add hello_callback to the + class_builder<> declaration in our module initialization function, and when we define the function, we must tell py_cpp about the default implementation:

     // Create the Python type object for our extension class
    -boost::python::class_builder<hello::world,world_callback> world_class(hello, "world");
    +"hello_class">Python type object for our extension class
    +boost::python::class_builder<hello,hello_callback> hello_class(hello, "hello");
     // Add a virtual member function
    -world_class.def(&world::get, "get", &world_callback::default_get);
    +hello_class.def(&hello::greet, "greet", &hello_callback::default_greet);
     

    - Now our subclass of hello.world behaves as expected: + Now our Python subclass of hello behaves as expected:

    ->>> class my_subclass(hello.world):
    +>>> class wordy(hello):
     ...     def greet(self):
    -...         return 'hello, world'
    +...         return hello.greet(self) + ', where the weather is fine'
     ...
    ->>> hello.length(my_subclass())
    -12
    +>>> hi2 = wordy('Florida')
    +>>> hi2.greet()
    +'Hello from Florida, where the weather is fine'
    +>>> invite(hi2)
    +'Hello from Florida, where the weather is fine! Please come soon!'
     
    -

    *You may ask, "Why do we need this derived class? This could have been designed so that everything gets done right - inside of hello::world." One of the goals of py_cpp is to be + inside of hello." One of the goals of py_cpp 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. To unintrusively hook into the virtual functions so that a Python @@ -117,10 +133,10 @@ world_class.def(&world::get, "get", &world_callback::default_get) deal with than a virtual function with a default implementation. First of all, you obviously don't need to supply a default implementation. Secondly, you don't need to call - def() on the extension_class<> instance + def() on the extension_class<> instance for the virtual function. In fact, you wouldn't want to: if the corresponding attribute on the Python class stays undefined, you'll get an - AttributeError in Python when you try to call the function, + AttributeError in Python when you try to call the function, indicating that it should have been implemented. For example:

    @@ -132,11 +148,7 @@ struct baz_callback {
         int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
     };
     
    -extern "C"
    -#ifdef _WIN32
    -__declspec(dllexport)
    -#endif
    -initfoobar()
    +BOOST_PYTHON_MODULE_INIT(foobar)
     {
         try
         {
    @@ -182,14 +194,14 @@ href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR
           Next: Function Overloading
    -      Previous: A Simple Example Using py_cpp
    +      Previous: Exporting Classes
           Up: Top
         

    - © Copyright David Abrahams 2000. Permission to copy, use, modify, + © Copyright David Abrahams 2001. 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.

    - Updated: Nov 26, 2000 + Updated: Mar 6, 2001 diff --git a/doc/pickle.html b/doc/pickle.html index 0e64d6fc..7b559e68 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -1,6 +1,6 @@ - BPL Pickle Support + Boost.Python Pickle Support @@ -11,7 +11,7 @@


    -

    BPL Pickle Support

    +

    Boost.Python Pickle Support

    Pickle is a Python module for object serialization, also known as persistence, marshalling, or flattening. @@ -39,16 +39,16 @@ described in detail in the Python Library Reference for pickle:

    -

    The BPL Pickle Interface

    +

    The Boost.Python Pickle Interface

    -At the user level, the BPL pickle interface involves three special +At the user level, the Boost.Python pickle interface involves three special methods:
    __getinitargs__
    - When an instance of a BPL extension class is pickled, the pickler + 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. When the instance is restored by the unpickler, the contents of this tuple are used as the arguments for @@ -63,7 +63,7 @@ methods: __getstate__
    - When an instance of a BPL extension class is pickled, the pickler + 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. @@ -76,7 +76,7 @@ methods: __setstate__
    - When an instance of a BPL extension class is restored by the + When an instance of a Boost.Python extension class is restored by the unpickler, 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 @@ -96,13 +96,13 @@ __setstate__ methods can do what they want.

    Pitfalls and Safety Guards

    -In BPL extension modules with many extension classes, providing +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. However, the -author of a BPL extension module might not anticipate correctly which +author of a Boost.Python extension module might not anticipate correctly which classes need support for pickle. Unfortunately, the pickle protocol -described above has two important pitfalls that the end user of a BPL +described above has two important pitfalls that the end user of a Boost.Python extension module might not be aware of:
    @@ -116,10 +116,10 @@ Both __getinitargs__ and __getstate__ are not defined. that of the new instance.

    - However, most C++ classes wrapped with the BPL will have member data + However, most C++ classes wrapped with Boost.Python will have member data that are not restored correctly by this procedure. To alert the user to this problem, a safety guard is provided. If both __getinitargs__ - and __getstate__ are not defined, the BPL tests if the class has an + and __getstate__ are not defined, Boost.Python tests if the class has an attribute __dict_defines_state__. An exception is raised if this attribute is not defined: @@ -151,7 +151,7 @@ Both __getinitargs__ and __getstate__ are not defined. __getstate__ is defined and the instance's __dict__ is not empty.

    - The author of a BPL extension class might provide a __getstate__ + The author of a Boost.Python extension class might provide a __getstate__ method without considering the possibilities that:

    @@ -170,7 +170,7 @@ __getstate__ is defined and the instance's __dict__ is not empty. 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, the BPL tests if the class has an attribute + not empty, Boost.Python tests if the class has an attribute __getstate_manages_dict__. An exception is raised if this attribute is not defined: diff --git a/doc/pointers.html b/doc/pointers.html index e26cea02..fdbee797 100644 --- a/doc/pointers.html +++ b/doc/pointers.html @@ -13,7 +13,7 @@

    In general, raw pointers passed to or returned from functions are problematic -for BPL because pointers have too many potential meanings. Is it an iterator? +for Boost.Python because pointers have too many potential meanings. Is it an iterator? A pointer to a single element? An array? When used as a return value, is the caller expected to manage (delete) the pointed-to object or is the pointer really just a reference? If the latter, what happens to Python references to the @@ -46,7 +46,7 @@ const Foo& f_wrapper() { return *f(); } my_module.def(f_wrapper, "f");

    -Foo must have a public copy constructor for this technique to work, since BPL +Foo must have a public copy constructor for this technique to work, since Boost.Python converts const T& values to_python by copying the T value into a new extension instance. diff --git a/doc/special.html b/doc/special.html index 50cee505..0caa1924 100644 --- a/doc/special.html +++ b/doc/special.html @@ -12,7 +12,7 @@ Overview

    - BPL supports all of the standard special method names supported by real Python class instances except __complex__ (more on the reasons my_class.def(boost::python::constructor<...>()) - (see section "A Simple Example Using BPL").

    + (see section "A Simple Example Using Boost.Python").

    __del__(self)
    @@ -104,7 +104,7 @@ std::string to_string(Foo const& f) boost::python::class_builder<Foo> foo_class(my_module, "Foo"); foo_class.def(&to_string, "__str__"); - Note that BPL also supports automatic wrapping of + Note that Boost.Python also supports automatic wrapping of __str__ and __cmp__. This is explained in the next section and the Table of Automatically Wrapped Methods. @@ -117,7 +117,7 @@ foo_class.def(&to_string, "__str__"); href="http://www.python.org/doc/current/ref/numeric-types.html">numeric protocols. This is the same basic technique used to expose to_string() as __str__() above, and is covered in detail below. BPL also supports + href="#numeric_manual">covered in detail below. Boost.Python also supports automatic wrapping of numeric operators whenever they have already been defined in C++. @@ -174,7 +174,7 @@ a = i + b; bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>()); bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>()); - BPL uses overloading to register several variants of the same + Boost.Python uses overloading to register several variants of the same operation (more on this in the context of coercion). Again, several operators can be exported at once:
    @@ -283,13 +283,13 @@ bignum_class.def(&rmod,  "__rmod__");
           coercion functions can be difficult if many type combinations must be
           supported. 
           

    - BPL solves this problem the same way that C++ does: with overloading. This technique drastically simplifies the code neccessary to support operators: you just register - operators for all desired type combinations, and BPL automatically + operators for all desired type combinations, and Boost.Python automatically ensures that the correct function is called in each case; there is no need for user-defined coercion functions. To enable operator - overloading, BPL provides a standard coercion which is implicitly + overloading, Boost.Python provides a standard coercion which is implicitly registered whenever automatic operator wrapping is used.

    If you wrap all operator functions manually, but still want to use @@ -370,7 +370,7 @@ bignum_class.def((ternary_function2)&power, "__pow__"); In the second variant, however, BigNum appears only as second argument, and in the last one it's the third argument. These functions - must be presented to BPL such that that the BigNum + must be presented to Boost.Python such that that the BigNum argument appears in first position:

    @@ -397,7 +397,7 @@ Note that "__rrpow__" is an extension not present in plain Python.
     
     

    Table of Automatically Wrapped Methods

    - BPL can automatically wrap the following special methods: @@ -772,13 +772,13 @@ KeyError: 2

    Customized Attribute Access

    - Just like built-in Python classes, BPL extension classes support special the usual attribute access methods __getattr__, __setattr__, and __delattr__. Because writing these functions can be tedious in the common case where the attributes being accessed are - known statically, BPL checks the special names + known statically, Boost.Python checks the special names

    • @@ -794,7 +794,7 @@ KeyError: 2 following shows how we can implement a ``computed attribute'' in Python:
      ->>> class Range(AnyBPLExtensionClass):
      +>>> class Range(AnyBoost.PythonExtensionClass):
       ...    def __init__(self, start, end):
       ...        self.start = start
       ...        self.end = end
      @@ -810,7 +810,7 @@ KeyError: 2
                Direct Access to Data Members
             
             

      - BPL uses the special + Boost.Python uses the special __xxxattr__<name>__ functionality described above to allow direct access to data members through the following special functions on class_builder<> and diff --git a/doc/under-the-hood.html b/doc/under-the-hood.html index 902804d3..733f0f54 100644 --- a/doc/under-the-hood.html +++ b/doc/under-the-hood.html @@ -22,7 +22,7 @@ "example1.html#add_world_class">add it to the module it goes into the module's dictionary to be looked up under the name "world".

      - BPL uses C++'s template argument deduction mechanism to determine the + Boost.Python uses C++'s template argument deduction mechanism to determine the types of arguments to functions (except constructors, for which we must provide an argument list because they can't be named in C++). Then, it calls the appropriate @@ -48,7 +48,7 @@ the top of your module's init function, then def the member functions later to avoid problems with inter-class dependencies.

      - Next: Building a Module with BPL + Next: Building a Module with Boost.Python Previous: Special Method and Operator Support Up: Top

      From 00cea4ff83e2d64c3273fab652171cf4ca192a88 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:40:47 +0000 Subject: [PATCH 04/23] Added getting_started targets [SVN r9471] --- build/build.dsw | 34 ++++++++++++++++++++++++++++++++++ build/build.opt | Bin 86528 -> 116224 bytes 2 files changed, 34 insertions(+) diff --git a/build/build.dsw b/build/build.dsw index f4ee1a11..8de38493 100644 --- a/build/build.dsw +++ b/build/build.dsw @@ -30,6 +30,40 @@ Package=<4> ############################################################################### +Project: "getting_started1"=.\getting_started1\getting_started1.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name bpl_static + End Project Dependency +}}} + +############################################################################### + +Project: "getting_started2"=.\getting_started2\getting_started2.dsp - Package Owner=<4> + +Package=<5> +{{{ + begin source code control + getting_started2 + .\getting_started2 + end source code control +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name bpl_static + End Project Dependency +}}} + +############################################################################### + Project: "rwgk1"=.\rwgk1\rwgk1.dsp - Package Owner=<4> Package=<5> diff --git a/build/build.opt b/build/build.opt index 5086795feff7997de1d0b50d82b2404da330c819..89eb84a706504d37bff9685be4808fda8baf9b81 100644 GIT binary patch literal 116224 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 From 98b31ed07389a28079818dc2806674e5da1f2137 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:53:14 +0000 Subject: [PATCH 05/23] use BOOST_PYTHON_MODULE_INIT, update getting_started2 for better documentation [SVN r9472] --- example/getting_started1.cpp | 4 +--- example/getting_started2.cpp | 33 ++++++++++++++++---------------- example/getting_started3.cpp | 4 +--- example/getting_started4.cpp | 4 +--- example/getting_started5.cpp | 4 +--- example/test_getting_started2.py | 26 +++++++++++++++++-------- 6 files changed, 38 insertions(+), 37 deletions(-) diff --git a/example/getting_started1.cpp b/example/getting_started1.cpp index 9679a2a4..7a8e9087 100644 --- a/example/getting_started1.cpp +++ b/example/getting_started1.cpp @@ -12,9 +12,7 @@ namespace python = boost::python; // Python requires an exported function called init in every // extension module. This is where we build the module contents. -extern "C" -DL_EXPORT(void) -initgetting_started1() +BOOST_PYTHON_MODULE_INIT(getting_started1) { try { diff --git a/example/getting_started2.cpp b/example/getting_started2.cpp index 82b4a6df..72b04105 100644 --- a/example/getting_started2.cpp +++ b/example/getting_started2.cpp @@ -1,29 +1,28 @@ #include #include -#include -namespace python = boost::python; namespace { // Avoid cluttering the global namespace. // A friendly class. - class world + class hello { + public: + hello(const std::string& country) { this->country = country; } + std::string greet() const { return "Hello from " + country; } private: std::string country; - public: - world(const std::string& country) { this->country = country; } - std::string greet() const { return "Hello from " + country + "!"; } }; - // A function taking a world object as an argument. - std::string invite(const world& w) { - return w.greet() + " Please come soon!"; + // A function taking a hello object as an argument. + std::string invite(const hello& w) { + return w.greet() + "! Please come soon!"; } } -extern "C" -DL_EXPORT(void) -initgetting_started2() +#include +namespace python = boost::python; + +BOOST_PYTHON_MODULE_INIT(getting_started2) { try { @@ -31,18 +30,18 @@ initgetting_started2() python::module_builder this_module("getting_started2"); // Create the Python type object for our extension class. - python::class_builder world_class(this_module, "world"); + python::class_builder hello_class(this_module, "hello"); // Add the __init__ function. - world_class.def(python::constructor()); + hello_class.def(python::constructor()); // Add a regular member function. - world_class.def(&world::greet, "greet"); + hello_class.def(&hello::greet, "greet"); // Add invite() as a regular function to the module. this_module.def(invite, "invite"); - // Even better, invite() can also be made a member of world_class!!! - world_class.def(invite, "invite"); + // Even better, invite() can also be made a member of hello_class!!! + hello_class.def(invite, "invite"); } catch(...) { diff --git a/example/getting_started3.cpp b/example/getting_started3.cpp index 7e827249..799f5cac 100644 --- a/example/getting_started3.cpp +++ b/example/getting_started3.cpp @@ -91,9 +91,7 @@ namespace { // Avoid cluttering the global namespace. } } -extern "C" -DL_EXPORT(void) -initgetting_started3() +BOOST_PYTHON_MODULE_INIT(getting_started3) { try { diff --git a/example/getting_started4.cpp b/example/getting_started4.cpp index 0c7bd7ee..199ef7a9 100644 --- a/example/getting_started4.cpp +++ b/example/getting_started4.cpp @@ -74,9 +74,7 @@ namespace { // Avoid cluttering the global namespace. } } -extern "C" -DL_EXPORT(void) -initgetting_started4() +BOOST_PYTHON_MODULE_INIT(getting_started4) { try { diff --git a/example/getting_started5.cpp b/example/getting_started5.cpp index c9f1ce36..be033224 100644 --- a/example/getting_started5.cpp +++ b/example/getting_started5.cpp @@ -103,9 +103,7 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE BOOST_PYTHON_END_CONVERSION_NAMESPACE -extern "C" -DL_EXPORT(void) -initgetting_started5() +BOOST_PYTHON_MODULE_INIT(getting_started5) { try { diff --git a/example/test_getting_started2.py b/example/test_getting_started2.py index 09215816..49cf765d 100644 --- a/example/test_getting_started2.py +++ b/example/test_getting_started2.py @@ -1,11 +1,21 @@ -r'''>>> import getting_started2 - >>> w = getting_started2.world('California') - >>> print w.greet() - Hello from California! - >>> print getting_started2.invite(w) - Hello from California! Please come soon! - >>> print w.invite() - Hello from California! Please come soon! +r'''>>> from getting_started2 import * + >>> hi = hello('California') + >>> hi.greet() + 'Hello from California' + >>> invite(hi) + 'Hello from California! Please come soon!' + >>> hi.invite() + 'Hello from California! Please come soon!' + + >>> class wordy(hello): + ... def greet(self): + ... return hello.greet(self) + ', where the weather is fine' + ... + >>> hi2 = wordy('Florida') + >>> hi2.greet() + 'Hello from Florida, where the weather is fine' + >>> invite(hi2) + 'Hello from Florida! Please come soon!' ''' def run(args = None): From 041409d71570d18cd25351936c4f817db47cd520 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:53:56 +0000 Subject: [PATCH 06/23] use BOOST_PYTHON_MODULE_INIT [SVN r9473] --- test/comprehensive.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/comprehensive.cpp b/test/comprehensive.cpp index 3d173310..7699b01f 100644 --- a/test/comprehensive.cpp +++ b/test/comprehensive.cpp @@ -1131,11 +1131,7 @@ void init_module() boost_python_test.add(new boost::python::meta_class); } -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initboost_python_test() +BOOST_PYTHON_MODULE_INIT(boost_python_test) { try { bpl_test::init_module(); From a350b666faafe048311aabcc7d9baa48732fce72 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 03:56:25 +0000 Subject: [PATCH 07/23] Added BOOST_PYTHON_MODULE_INIT [SVN r9475] --- include/boost/python/detail/config.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 3207f7c6..9792695e 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -57,4 +57,10 @@ # define BOOST_CSTD_ std # endif +#ifdef _WIN32 +# define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name() +#else +# define BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name() +#endif + #endif // CONFIG_DWA052200_H_ From 5759ce9ba0ad80126051762d56492ce0a33b5239 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 22:27:22 +0000 Subject: [PATCH 08/23] no message [SVN r9482] --- build/getting_started1/getting_started1.dsp | 136 ++++++++++++++++++++ build/getting_started2/getting_started2.dsp | 135 +++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 build/getting_started1/getting_started1.dsp create mode 100644 build/getting_started2/getting_started2.dsp diff --git a/build/getting_started1/getting_started1.dsp b/build/getting_started1/getting_started1.dsp new file mode 100644 index 00000000..a41eb057 --- /dev/null +++ b/build/getting_started1/getting_started1.dsp @@ -0,0 +1,136 @@ +# Microsoft Developer Studio Project File - Name="getting_started1" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=getting_started1 - Win32 DebugPython +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "getting_started1.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "getting_started1.mak" CFG="getting_started1 - Win32 DebugPython" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "getting_started1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "getting_started1 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started1 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started1 - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DebugPython" +# PROP BASE Intermediate_Dir "DebugPython" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugPython" +# PROP Intermediate_Dir "DebugPython" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"DebugPython/boost_python_test_d.pdb" /debug /machine:I386 /out:"DebugPython/getting_started1_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "getting_started1 - Win32 Release" +# Name "getting_started1 - Win32 Debug" +# Name "getting_started1 - Win32 DebugPython" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\example\getting_started1.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/build/getting_started2/getting_started2.dsp b/build/getting_started2/getting_started2.dsp new file mode 100644 index 00000000..284bab21 --- /dev/null +++ b/build/getting_started2/getting_started2.dsp @@ -0,0 +1,135 @@ +# Microsoft Developer Studio Project File - Name="getting_started2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=getting_started2 - Win32 DebugPython +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "getting_started2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "getting_started2.mak" CFG="getting_started2 - Win32 DebugPython" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "getting_started2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "getting_started2 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "getting_started2" +# PROP Scc_LocalPath "." +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "getting_started2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs" + +!ELSEIF "$(CFG)" == "getting_started2 - Win32 DebugPython" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "getting_started2___Win32_DebugPython" +# PROP BASE Intermediate_Dir "getting_started2___Win32_DebugPython" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "getting_started2___Win32_DebugPython" +# PROP Intermediate_Dir "getting_started2___Win32_DebugPython" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"DebugPython/getting_started2_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\pcbuild" + +!ENDIF + +# Begin Target + +# Name "getting_started2 - Win32 Release" +# Name "getting_started2 - Win32 Debug" +# Name "getting_started2 - Win32 DebugPython" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\example\getting_started2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project From 945344b3cd440b9260b2536cb2b3c3f9e0c24714 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 7 Mar 2001 23:31:32 +0000 Subject: [PATCH 09/23] *** empty log message *** [SVN r9483] --- doc/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.html b/doc/index.html index 5a64bf62..c6e0722e 100644 --- a/doc/index.html +++ b/doc/index.html @@ -97,7 +97,7 @@ among others.

    • 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,n and Barry Scott took the + 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. From bdbd9a0f5fcd711bd3fbca0477914fbf9c741348 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 8 Mar 2001 01:32:12 +0000 Subject: [PATCH 10/23] class_builder -> class_builder<your_class> [SVN r9484] --- doc/pickle.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 7b559e68..ef3d8d0d 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -132,7 +132,7 @@ Both __getinitargs__ and __getstate__ are not defined. this is, e.g.:
      -    class_builder py_your_class(your_module, "your_class");
      +    class_builder<your_class> py_your_class(your_module, "your_class");
           py_your_class.dict_defines_state();
       
      @@ -185,7 +185,7 @@ __getstate__ is defined and the instance's __dict__ is not empty. E.g. in C++:
      -    class_builder py_your_class(your_module, "your_class");
      +    class_builder<your_class> py_your_class(your_module, "your_class");
           py_your_class.getstate_manages_dict();
       
      From a55948071695439f870126c1d686d4aeac4df8b3 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 8 Mar 2001 03:01:29 +0000 Subject: [PATCH 11/23] py_cpp => Boost.Python [SVN r9485] --- doc/overriding.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/overriding.html b/doc/overriding.html index 7b28add1..b29bf0e6 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -92,7 +92,7 @@ struct hello_callback : hello

      Finally, we add hello_callback to the class_builder<> declaration in our module initialization - function, and when we define the function, we must tell py_cpp about the default + function, and when we define the function, we must tell Boost.Python about the default implementation:

      @@ -120,7 +120,7 @@ hello_class.def(&hello::greet, "greet", &hello_callback::default_gree
           

      *You may ask, "Why do we need this derived class? This could have been designed so that everything gets done right - inside of hello." One of the goals of py_cpp is to be + inside of hello." 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. To unintrusively hook into the virtual functions so that a Python From 33ea0dbdeeadd3b4ad77f223843276d9a08867f6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 02:40:06 +0000 Subject: [PATCH 12/23] temp file before branching [SVN r9515] --- doc/cross_module_dependencies.html | 253 +++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 doc/cross_module_dependencies.html diff --git a/doc/cross_module_dependencies.html b/doc/cross_module_dependencies.html new file mode 100644 index 00000000..3d416bf5 --- /dev/null +++ b/doc/cross_module_dependencies.html @@ -0,0 +1,253 @@ + + + Cross-extension-module dependencies + + + +c++boost.gif (8819 bytes) + + +


      +

      Cross-extension-module dependencies

      + +It is good programming practice to organize large projects as modules +that interact with each other via well defined interfaces. With +Boost.Python it is possible to reflect this organization at the C++ +level at the Python level. This is, each logical C++ module can be +organized as a separate Python extension module. + +

      +At first sight this might seem natural and straightforward. However, it +is a fairly complex problem to establish cross-extension-module +dependencies while maintaining the same ease of use Boost.Python +provides for classes that are wrapped in the same extension module. To +a large extent this complexity can be hidden from the author of a +Boost.Python extension module, but not entirely. + +

      The recipe

      + +Suppose there is an extension module that exposes certain instances of +the C++ std::vector template library such that it can be used from +Python in the following manner: + +
      +import std_vector
      +v = std_vector.double([1, 2, 3, 4])
      +v.push_back(5)
      +v.size()
      +
      + +Suppose the std_vector module is done well and reflects all C++ +functions that are useful at the Python level, for all C++ built-in +data types (std_vector.int, std_vector.long, etc.). + +

      +Suppose further that there is statistic module with a C++ class that +has constructors or member functions that use or return a std::vector. +For example: + +

      +class xy {
      +  private:
      +    std::vector<double> m_x;
      +    std::vector<double> m_y;
      +  public:
      +    xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
      +    const std::vector<double>& x() const { return m_x; }
      +    const std::vector<double>& y() const { return m_y; }
      +    double correlation();
      +}
      +
      + +What is more natural then reusing the std_vector extension module to +expose these constructors or functions to Python? + +

      +Unfortunately, what seems natural needs a little work in both the +std_vector and the statistics module. + +

      +In the std_vector extension module, std::vector<double> needs to be +exposed to Python with the x_class_builder<> template instead of the +regular class_builder<>. For example: + +

      +  x_class_builder<std::vector<double> > v_double(std_vector_module, "double");
      +
      + +In the extension module that wraps class xy we need to use +the import_class_builder<> template: + +
      +  import_class_builder<std::vector<double> > v_double("std_vector", "double");
      +
      + +That is all. All the properties that are defined for std_vector.double +in the std_vector Boost.Python module will be available for the +returned objects of xy.x() and xy.y(). Similarly, the constructor for +xy will accept objects that were created by the std_vector module. + +

      Non-copyable types

      + +The x_class_builder<T> instantiates template functions that invoke the +copy constructor of T. For a T that is non-copyable this will result in +compile-time error messages. In such a case, another variety of the +class_builder<>, the xptr_class_builder<> must be used. +For example: + +
      +xptr_class_builder<store> py_store(your_module, "store");
      +
      + +The corresponding import_class_builder<> does not need any special +attention: + +
      +import_class_builder<store> py_store("noncopyable_export", "store");
      +
      + +

      Python module search path

      + +The std_vector and statistics modules can now be used in the following +way: + +
      +import std_vector
      +import statistics
      +x = std_vector.double([1, 2, 3, 4])
      +y = std_vector.double([2, 4, 6, 8])
      +xy = statistics.xy(x, y)
      +xy.correlation()
      +
      + +In this example it is clear that Python has to be able to find both the +std_vector and the statistics extension module. In other words, both +extension modules need to be in the Python module search path +(sys.path). + +

      +The situation is not always that obvious. Suppose the statistics +module has a random function that returns a vector of random +numbers with a given length: + +

      +import statistics
      +x = statistics.random(5)
      +y = statistics.random(5)
      +xy = statistics.xy(x, y)
      +xy.correlation()
      +
      + +A naive user will not easily anticipate that the std_vector module is +used to pass the x and y vectors around. If the std_vector module is in +the Python module search path, this form of ignorance is of no harm. +On the contrary, we are glad that we do not have to bother the user +with details like this. + +

      +If the std_vector module is not in the Python module search path, a +Python exception will be raised: + +

      +Traceback (innermost last):
      +  File "foo.py", line 2, in ?
      +    x = statistics.random(5)
      +ImportError: No module named std_vector
      +
      + +As is the case with any system of a non-trivial complexity, it is +important that the setup is consistent and complete. + +

      Two-way module dependencies

      + +Boost.Python supports two-way module dependencies. This is best +illustrated by a simple example. + +

      +Suppose there is a module ivect that implements vectors of integers, +and a similar module dvect that implements vectors of doubles. We want +to be able do convert an integer vector to a double vector and vice +versa. For example: + +

      +import ivect
      +iv = ivect.ivect((1,2,3,4,5))
      +dv = iv.as_dvect()
      +
      + +The last expression will implicitly import the dvect module in order to +enable the conversion of the C++ representation of dvect to a Python +object. The analogous is possible for a dvect: + +
      +import dvect
      +dv = dvect.dvect((1,2,3,4,5))
      +iv = dv.as_ivect()
      +
      + +Now the ivect module is imported implicitly. + +

      +Note that the two-way dependencies are possible because the +dependencies are resolved only when needed. This is, the initialization +of the ivect module does not rely on the dvect module, and vice versa. +Only if as_dvect() or as_ivect() is actually invoked will the +corresponding module be implicitly imported. This also means that, for +example, the dvect module does not have to be available at all if +as_dvect() is never used. + +

      Clarification of compile-time and link-time dependencies

      + +Boost.Python's support for resolving cross-module dependencies at +runtime does not imply that compile-time dependencies are eliminated. +For example, the statistics extension module in the example above will +need to #include <vector>. This is immediately obvious from the +definition of class xy. + +

      +If a library is wrapped that consists of both header files and compiled +components (e.g. libdvect.a, dvect.lib, etc.), both the Boost.Python +extension module with the x_class_wrapper<> and the module with the +import_class_wrapper<> need to be linked against the object library. +Ideally one would build a shared library (e.g. libdvect.so, dvect.dll, +etc.). However, this introduces the issue of getting the search path +for the dynamic loading configured correctly. For small libraries it is +therefore often more convenient to ignore the fact that the object +files are loaded into memory more than once. + +

      +The main purpose of Boost.Python's support for resolving cross-module +dependencies at runtime is to allow for a modular system layout. With +this support it is straightforward to reflect C++ code organization at +the Python level. Without the cross-module support, a multi-purpose +module like std_vector would be impractical because the entire wrapper +code would somehow have to be duplicated in all extension modules that +use it, making them harder to maintain and harder to build. + +

      +Finally, there is an important psychological component. If a group of +classes is lumped together with many others in a huge module, the +authors will have difficulties in being identified with their work. +The situation is much more transparent if the work is represented by +a module with a recognizable name. This is not just a question of +strong egos, but also of getting credit and funding. + +

      Why not use the x_class_builder universally?

      + +There is some overhead associated with the Boost.Python cross-module +support. Depending on the platform, the code generated by +x_class_builder<> is roughly 10%-20% larger than that generated by +class_builder<>. For a large extension module with many wrapped +classes, this could mean a significant difference. Therefore the +general recommendation is to use x_class_wrapper<> only for classes +that are likely to be used as function arguments or return values in +other modules. + +
      +
      +Author: Ralf W. Grosse-Kunstleve, March 2001 +
      + From a6b0fa546a1d0f0cfc08068ebaa9bfad3c7c8b9a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 02:41:16 +0000 Subject: [PATCH 13/23] temp file removed after branching. [SVN r9516] --- doc/cross_module_dependencies.html | 253 ----------------------------- 1 file changed, 253 deletions(-) delete mode 100644 doc/cross_module_dependencies.html diff --git a/doc/cross_module_dependencies.html b/doc/cross_module_dependencies.html deleted file mode 100644 index 3d416bf5..00000000 --- a/doc/cross_module_dependencies.html +++ /dev/null @@ -1,253 +0,0 @@ - - - Cross-extension-module dependencies - - - -c++boost.gif (8819 bytes) - - -
      -

      Cross-extension-module dependencies

      - -It is good programming practice to organize large projects as modules -that interact with each other via well defined interfaces. With -Boost.Python it is possible to reflect this organization at the C++ -level at the Python level. This is, each logical C++ module can be -organized as a separate Python extension module. - -

      -At first sight this might seem natural and straightforward. However, it -is a fairly complex problem to establish cross-extension-module -dependencies while maintaining the same ease of use Boost.Python -provides for classes that are wrapped in the same extension module. To -a large extent this complexity can be hidden from the author of a -Boost.Python extension module, but not entirely. - -

      The recipe

      - -Suppose there is an extension module that exposes certain instances of -the C++ std::vector template library such that it can be used from -Python in the following manner: - -
      -import std_vector
      -v = std_vector.double([1, 2, 3, 4])
      -v.push_back(5)
      -v.size()
      -
      - -Suppose the std_vector module is done well and reflects all C++ -functions that are useful at the Python level, for all C++ built-in -data types (std_vector.int, std_vector.long, etc.). - -

      -Suppose further that there is statistic module with a C++ class that -has constructors or member functions that use or return a std::vector. -For example: - -

      -class xy {
      -  private:
      -    std::vector<double> m_x;
      -    std::vector<double> m_y;
      -  public:
      -    xy(const std::vector<double>& x, const std::vector<double>& y) : m_x(x), m_y(y) {}
      -    const std::vector<double>& x() const { return m_x; }
      -    const std::vector<double>& y() const { return m_y; }
      -    double correlation();
      -}
      -
      - -What is more natural then reusing the std_vector extension module to -expose these constructors or functions to Python? - -

      -Unfortunately, what seems natural needs a little work in both the -std_vector and the statistics module. - -

      -In the std_vector extension module, std::vector<double> needs to be -exposed to Python with the x_class_builder<> template instead of the -regular class_builder<>. For example: - -

      -  x_class_builder<std::vector<double> > v_double(std_vector_module, "double");
      -
      - -In the extension module that wraps class xy we need to use -the import_class_builder<> template: - -
      -  import_class_builder<std::vector<double> > v_double("std_vector", "double");
      -
      - -That is all. All the properties that are defined for std_vector.double -in the std_vector Boost.Python module will be available for the -returned objects of xy.x() and xy.y(). Similarly, the constructor for -xy will accept objects that were created by the std_vector module. - -

      Non-copyable types

      - -The x_class_builder<T> instantiates template functions that invoke the -copy constructor of T. For a T that is non-copyable this will result in -compile-time error messages. In such a case, another variety of the -class_builder<>, the xptr_class_builder<> must be used. -For example: - -
      -xptr_class_builder<store> py_store(your_module, "store");
      -
      - -The corresponding import_class_builder<> does not need any special -attention: - -
      -import_class_builder<store> py_store("noncopyable_export", "store");
      -
      - -

      Python module search path

      - -The std_vector and statistics modules can now be used in the following -way: - -
      -import std_vector
      -import statistics
      -x = std_vector.double([1, 2, 3, 4])
      -y = std_vector.double([2, 4, 6, 8])
      -xy = statistics.xy(x, y)
      -xy.correlation()
      -
      - -In this example it is clear that Python has to be able to find both the -std_vector and the statistics extension module. In other words, both -extension modules need to be in the Python module search path -(sys.path). - -

      -The situation is not always that obvious. Suppose the statistics -module has a random function that returns a vector of random -numbers with a given length: - -

      -import statistics
      -x = statistics.random(5)
      -y = statistics.random(5)
      -xy = statistics.xy(x, y)
      -xy.correlation()
      -
      - -A naive user will not easily anticipate that the std_vector module is -used to pass the x and y vectors around. If the std_vector module is in -the Python module search path, this form of ignorance is of no harm. -On the contrary, we are glad that we do not have to bother the user -with details like this. - -

      -If the std_vector module is not in the Python module search path, a -Python exception will be raised: - -

      -Traceback (innermost last):
      -  File "foo.py", line 2, in ?
      -    x = statistics.random(5)
      -ImportError: No module named std_vector
      -
      - -As is the case with any system of a non-trivial complexity, it is -important that the setup is consistent and complete. - -

      Two-way module dependencies

      - -Boost.Python supports two-way module dependencies. This is best -illustrated by a simple example. - -

      -Suppose there is a module ivect that implements vectors of integers, -and a similar module dvect that implements vectors of doubles. We want -to be able do convert an integer vector to a double vector and vice -versa. For example: - -

      -import ivect
      -iv = ivect.ivect((1,2,3,4,5))
      -dv = iv.as_dvect()
      -
      - -The last expression will implicitly import the dvect module in order to -enable the conversion of the C++ representation of dvect to a Python -object. The analogous is possible for a dvect: - -
      -import dvect
      -dv = dvect.dvect((1,2,3,4,5))
      -iv = dv.as_ivect()
      -
      - -Now the ivect module is imported implicitly. - -

      -Note that the two-way dependencies are possible because the -dependencies are resolved only when needed. This is, the initialization -of the ivect module does not rely on the dvect module, and vice versa. -Only if as_dvect() or as_ivect() is actually invoked will the -corresponding module be implicitly imported. This also means that, for -example, the dvect module does not have to be available at all if -as_dvect() is never used. - -

      Clarification of compile-time and link-time dependencies

      - -Boost.Python's support for resolving cross-module dependencies at -runtime does not imply that compile-time dependencies are eliminated. -For example, the statistics extension module in the example above will -need to #include <vector>. This is immediately obvious from the -definition of class xy. - -

      -If a library is wrapped that consists of both header files and compiled -components (e.g. libdvect.a, dvect.lib, etc.), both the Boost.Python -extension module with the x_class_wrapper<> and the module with the -import_class_wrapper<> need to be linked against the object library. -Ideally one would build a shared library (e.g. libdvect.so, dvect.dll, -etc.). However, this introduces the issue of getting the search path -for the dynamic loading configured correctly. For small libraries it is -therefore often more convenient to ignore the fact that the object -files are loaded into memory more than once. - -

      -The main purpose of Boost.Python's support for resolving cross-module -dependencies at runtime is to allow for a modular system layout. With -this support it is straightforward to reflect C++ code organization at -the Python level. Without the cross-module support, a multi-purpose -module like std_vector would be impractical because the entire wrapper -code would somehow have to be duplicated in all extension modules that -use it, making them harder to maintain and harder to build. - -

      -Finally, there is an important psychological component. If a group of -classes is lumped together with many others in a huge module, the -authors will have difficulties in being identified with their work. -The situation is much more transparent if the work is represented by -a module with a recognizable name. This is not just a question of -strong egos, but also of getting credit and funding. - -

      Why not use the x_class_builder universally?

      - -There is some overhead associated with the Boost.Python cross-module -support. Depending on the platform, the code generated by -x_class_builder<> is roughly 10%-20% larger than that generated by -class_builder<>. For a large extension module with many wrapped -classes, this could mean a significant difference. Therefore the -general recommendation is to use x_class_wrapper<> only for classes -that are likely to be used as function arguments or return values in -other modules. - -
      -
      -Author: Ralf W. Grosse-Kunstleve, March 2001 -
      - From 55321b87785ef71e51669bc562211dc534884032 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 18:59:59 +0000 Subject: [PATCH 14/23] HTML 4.0 Strict fixes. [SVN r9530] --- doc/pickle.html | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index ef3d8d0d..49f5c605 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -1,15 +1,15 @@ - - - Boost.Python Pickle Support - - + + +Boost.Python Pickle Support + +
      c++boost.gif (8819 bytes) -

      Boost.Python Pickle Support

      @@ -28,15 +28,14 @@ can be written to a file.

      The Boost Python Library supports the pickle module by emulating the interface implemented by Jim Fulton's ExtensionClass module that is -included in the ZOPE distribution -(http://www.zope.org/). +included in the +ZOPE +distribution. This interface is similar to that for regular Python classes as -described in detail in the Python Library Reference for pickle: - -

      - http://www.python.org/doc/current/lib/module-pickle.html -
      +described in detail in the +Python Library Reference for pickle.

      The Boost.Python Pickle Interface

      @@ -220,4 +219,4 @@ __getstate__ is defined and the instance's __dict__ is not empty.
      Author: Ralf W. Grosse-Kunstleve, March 2001
      - +
      From 494f12090f4090d1678f7f2b5fb06130e9814fca Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 19:02:12 +0000 Subject: [PATCH 15/23] Use only one

      (although the validator did not complain). [SVN r9531] --- doc/pickle.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 49f5c605..3ec8c928 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -38,7 +38,7 @@ described in detail in the >Python Library Reference for pickle.
      -

      The Boost.Python Pickle Interface

      +

      The Boost.Python Pickle Interface

      At the user level, the Boost.Python pickle interface involves three special methods: @@ -93,7 +93,7 @@ returned by __getstate__ need not be a dictionary. The __getstate__ and __setstate__ methods can do what they want.
      -

      Pitfalls and Safety Guards

      +

      Pitfalls and Safety Guards

      In Boost.Python extension modules with many extension classes, providing complete pickle support for all classes would be a significant @@ -202,7 +202,7 @@ __getstate__ is defined and the instance's __dict__ is not empty.
      -

      Practical Advice

      +

      Practical Advice

      • From 585063f6e18a37e90febc4409595f99f8d35c3f8 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 9 Mar 2001 20:04:56 +0000 Subject: [PATCH 16/23] Small enhancements. [SVN r9532] --- doc/pickle.html | 136 +++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 59 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 3ec8c928..39cb07dc 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -45,81 +45,87 @@ methods:
        -__getinitargs__ +__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. When the instance is restored by the + 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, the class constructor will be - called without arguments. + If __getinitargs__ is not defined, the class constructor + will be called without arguments.

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

        - If __getstate__ is not defined, the instance's __dict__ is pickled - (if it is not empty). + If __getstate__ is not defined, the instance's + __dict__ is pickled (if it is not empty).

        -__setstate__ +__setstate__
        When an instance of a Boost.Python extension class is restored by the unpickler, 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. + __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.

        - If __setstate__ is not defined, the result of __getstate__ must be - a Python dictionary. The items of this dictionary are added to - the instance's __dict__. + If __setstate__ is not defined, the result of + __getstate__ must be a Python dictionary. The items of this + dictionary are added to the instance's __dict__. +

        -If both __getstate__ and __setstate__ are defined, the Python object -returned by __getstate__ need not be a dictionary. The __getstate__ and -__setstate__ methods can do what they want. +If both __getstate__ and __setstate__ are defined, +the Python object returned by __getstate__ need not be a +dictionary. The __getstate__ and __setstate__ methods +can do what they want.

        Pitfalls and Safety Guards

        -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. However, the -author of a Boost.Python extension module might not anticipate correctly which -classes need support for pickle. Unfortunately, the pickle protocol -described above has two important pitfalls that the end user of a Boost.Python -extension module might not be aware of: +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. +However, the author of a Boost.Python extension module might not +anticipate correctly which classes need support for pickle. +Unfortunately, the pickle protocol described above has two important +pitfalls that the end user of a Boost.Python extension module might not +be aware of:
        Pitfall 1: -Both __getinitargs__ and __getstate__ are not defined. +Both __getinitargs__ and __getstate__ are not defined.
        In this situation the unpickler calls the class constructor without - arguments and then adds the __dict__ that was pickled by default to - that of the new instance. + arguments and then adds the __dict__ that was pickled by + default to that of the new instance.

        - However, most C++ classes wrapped with Boost.Python will have member data - that are not restored correctly by this procedure. To alert the user - to this problem, a safety guard is provided. If both __getinitargs__ - and __getstate__ are not defined, Boost.Python tests if the class has an - attribute __dict_defines_state__. An exception is raised if this + However, most C++ classes wrapped with Boost.Python will have member + data that are not restored correctly by this procedure. To alert the + user to this problem, a safety guard is provided. If both + __getinitargs__ and __getstate__ are not defined, + Boost.Python tests if the class has an attribute + __dict_defines_state__. An exception is raised if this attribute is not defined:

        @@ -147,41 +153,44 @@ Both __getinitargs__ and __getstate__ are not defined.
         

        Pitfall 2: -__getstate__ is defined and the instance's __dict__ is not empty. +__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: + The author of a Boost.Python extension class might provide a + __getstate__ method without considering the possibilities + that:

        • - his class is used 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. + 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. + 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: + 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 both at the C++ and the Python - level. Finally, the safety guard should intentionally be overridden. - E.g. in C++: + __getstate__ and __setstate__ methods manage the + instances's __dict__ correctly. Note that this can be done + both at the C++ and the Python level. Finally, the safety guard + should intentionally be overridden. E.g. in C++:
             class_builder<your_class> py_your_class(your_module, "your_class");
        @@ -206,15 +215,24 @@ __getstate__ is defined and the instance's __dict__ is not empty.
         
         
        • - Avoid using __getstate__ if the instance can also be reconstructed - by way of __getinitargs__. This automatically avoids Pitfall 2. + Avoid using __getstate__ if the instance can also be + reconstructed by way of __getinitargs__. This automatically + avoids Pitfall 2.

        • - If __getstate__ is required, include the instance's __dict__ in the - Python object that is returned. + If __getstate__ is required, include the instance's + __dict__ in the Python object that is returned. +
        +
        +

        Example

        + +An example that shows how to provide pickle support is available in the +boost/lib/python/example directory +(getting_started3.cpp). +
        Author: Ralf W. Grosse-Kunstleve, March 2001 From f5416ebce07b914ed6fd83754f414e53bd2b5563 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Mar 2001 00:36:03 +0000 Subject: [PATCH 17/23] Fixed some doc bugs and improved an example [SVN r9533] --- doc/overriding.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/overriding.html b/doc/overriding.html index b29bf0e6..0fc7a2e6 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -142,6 +142,7 @@ hello_class.def(&hello::greet, "greet", &hello_callback::default_gree
         struct baz {
             virtual int pure(int) = 0;
        +    int calls_pure(int x) { return pure(x) + 1000; }
         };
         
         struct baz_callback {
        @@ -154,7 +155,7 @@ BOOST_PYTHON_MODULE_INIT(foobar)
             {
                boost::python::module_builder foobar("foobar");
                boost::python::class_builder<baz,baz_callback> baz_class("baz");
        -       baz_class.def(&baz::pure, "pure");
        +       baz_class.def(&baz::calls_pure, "calls_pure");
             }
             catch(...)
             {
        @@ -173,12 +174,18 @@ BOOST_PYTHON_MODULE_INIT(foobar)
         Traceback (innermost last):
           File "<stdin>", line 1, in ?
         AttributeError: pure
        +>>> x.calls_pure(1)
        +Traceback (innermost last):
        +  File "<stdin>", line 1, in ?
        +AttributeError: pure
         >>> class mumble(baz):
         ...    def pure(self, x): return x + 1
         ...
         >>> y = mumble()
         >>> y.pure(99)
         100
        +>>> y.calls_pure(99)
        +1100
         

      Private Non-Pure Virtual Functions

      @@ -192,6 +199,7 @@ this limited way without breaking binary compatibility (though it will certainly break the ODR). +

      Next: Function Overloading Previous: Exporting Classes From 678fa006de24673b654fc057a165e79a2108a734 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 10 Mar 2001 08:23:37 +0000 Subject: [PATCH 18/23] Copyright notice & minor fixes. [SVN r9536] --- doc/pickle.html | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/pickle.html b/doc/pickle.html index 39cb07dc..842112d3 100644 --- a/doc/pickle.html +++ b/doc/pickle.html @@ -8,7 +8,7 @@ c++boost.gif (8819 bytes) + width="277" height="86">


      Boost.Python Pickle Support

      @@ -229,12 +229,17 @@ Both __getinitargs__ and __getstate__ are not defined.

      Example

      -An example that shows how to provide pickle support is available in the +An example that shows how to configure pickle support is available in the boost/lib/python/example directory (getting_started3.cpp).
      -
      -Author: Ralf W. Grosse-Kunstleve, March 2001 -
      +© Copyright Ralf W. Grosse-Kunstleve 2001. 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. + +

      +Updated: March 10, 2001 From 14acb1af8c1ef20c1a49ea1a2901e6b49817f2e2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 10 Mar 2001 19:09:10 +0000 Subject: [PATCH 19/23] Fix bugs (m_self => self) [SVN r9539] --- doc/overriding.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/overriding.html b/doc/overriding.html index 0fc7a2e6..66c3610c 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -79,13 +79,13 @@ struct hello_callback : hello // Override greet to call back into Python std::string greet() const // 4 - { return boost::python::callback<std::string>::call_method(m_self, "greet"); } + { return boost::python::callback<std::string>::call_method(self, "greet"); } // Supplies the default implementation of greet static std::string default_greet(const hello& self) const // 5 { return self.hello::greet(); } private: - PyObject* m_self; // 1 + PyObject* self; // 1 };

    • From 7dc8fab961c798a832c959096462f901c8ec48f7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 11 Mar 2001 21:29:31 +0000 Subject: [PATCH 20/23] 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) [SVN r9544] --- src/conversions.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/conversions.cpp b/src/conversions.cpp index 88e30048..9445c7f3 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -7,6 +7,7 @@ // producing this work. // // Revision History: +// 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) // 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) // 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) @@ -149,7 +150,7 @@ int from_python(PyObject* p, boost::python::type type) PyObject* to_python(unsigned int i) { - return integer_to_python(i); + return integer_to_python(i); } unsigned int from_python(PyObject* p, boost::python::type type) @@ -169,7 +170,7 @@ float from_python(PyObject* p, boost::python::type) PyObject* to_python(unsigned short i) { - return integer_to_python(i); + return integer_to_python(i); } unsigned short from_python(PyObject* p, boost::python::type type) @@ -197,7 +198,7 @@ char from_python(PyObject* p, boost::python::type) PyObject* to_python(unsigned char i) { - return integer_to_python(i); + return integer_to_python(i); } unsigned char from_python(PyObject* p, boost::python::type type) @@ -207,7 +208,7 @@ unsigned char from_python(PyObject* p, boost::python::type type) PyObject* to_python(signed char i) { - return integer_to_python(i); + return integer_to_python(i); } signed char from_python(PyObject* p, boost::python::type type) @@ -243,12 +244,15 @@ const char* from_python(PyObject* p, boost::python::type) PyObject* to_python(const std::string& s) { - return PyString_FromString(s.c_str()); + return PyString_FromStringAndSize(s.data(), s.size()); } std::string from_python(PyObject* p, boost::python::type) { - return std::string(from_python(p, boost::python::type())); + char* buffer = 0; + int length = 0; + int rc = PyString_AsStringAndSize(p, &buffer, &length); + return std::string(buffer, length); } bool from_python(PyObject* p, boost::python::type) From ed34cd45f1da43539e40e8b9d51e360312c422c0 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 12 Mar 2001 19:32:40 +0000 Subject: [PATCH 21/23] Python 1.5.2 fixes [SVN r9546] --- src/conversions.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/conversions.cpp b/src/conversions.cpp index 9445c7f3..1bc923b1 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -7,6 +7,7 @@ // producing this work. // // Revision History: +// 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve) // 11 Mar 01 std::string *MAY* include nulls (Alex Martelli) // 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams) // 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve) @@ -249,10 +250,7 @@ PyObject* to_python(const std::string& s) std::string from_python(PyObject* p, boost::python::type) { - char* buffer = 0; - int length = 0; - int rc = PyString_AsStringAndSize(p, &buffer, &length); - return std::string(buffer, length); + return std::string(PyString_AsString(p), PyString_Size(p)); } bool from_python(PyObject* p, boost::python::type) From ff04d9f03c85e173a0d6084d20ef3f2416b699c7 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 12 Mar 2001 19:34:14 +0000 Subject: [PATCH 22/23] Minute enhancement. [SVN r9547] --- doc/overriding.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/overriding.html b/doc/overriding.html index 66c3610c..af458d79 100644 --- a/doc/overriding.html +++ b/doc/overriding.html @@ -82,8 +82,8 @@ struct hello_callback : hello { return boost::python::callback<std::string>::call_method(self, "greet"); } // Supplies the default implementation of greet - static std::string default_greet(const hello& self) const // 5 - { return self.hello::greet(); } + static std::string default_greet(const hello& self_) const // 5 + { return self_.hello::greet(); } private: PyObject* self; // 1 }; From 012b4025a48e056da251b58eb50c402079740894 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 13 Mar 2001 00:01:06 +0000 Subject: [PATCH 23/23] temp files before branching [SVN r9549] --- example/pickle1.cpp | 57 +++++++++++++++++++ example/pickle2.cpp | 80 ++++++++++++++++++++++++++ example/pickle3.cpp | 121 ++++++++++++++++++++++++++++++++++++++++ example/test_pickle1.py | 31 ++++++++++ example/test_pickle2.py | 45 +++++++++++++++ example/test_pickle3.py | 38 +++++++++++++ 6 files changed, 372 insertions(+) create mode 100644 example/pickle1.cpp create mode 100644 example/pickle2.cpp create mode 100644 example/pickle3.cpp create mode 100644 example/test_pickle1.py create mode 100644 example/test_pickle2.py create mode 100644 example/test_pickle3.py diff --git a/example/pickle1.cpp b/example/pickle1.cpp new file mode 100644 index 00000000..2f786f69 --- /dev/null +++ b/example/pickle1.cpp @@ -0,0 +1,57 @@ +/* + This example shows how to make an Extension Class "pickleable". + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + private: + std::string country; + int secret_number; + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle1) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle1"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle2.cpp b/example/pickle2.cpp new file mode 100644 index 00000000..c33776a0 --- /dev/null +++ b/example/pickle2.cpp @@ -0,0 +1,80 @@ +/* + This example shows how to make an Extension Class "pickleable". + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + void world_setstate(world& w, python::tuple state) { + if (state.size() != 1) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + int number = state[0].get(); + if (number != 42) + w.set_secret_number(number); + } +} + +BOOST_PYTHON_MODULE_INIT(pickle2) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle2"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def(world_getstate, "__getstate__"); + world_class.def(world_setstate, "__setstate__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/pickle3.cpp b/example/pickle3.cpp new file mode 100644 index 00000000..19ddec43 --- /dev/null +++ b/example/pickle3.cpp @@ -0,0 +1,121 @@ +/* + This example shows how to make an Extension Class "pickleable". + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + // Support for pickle. + python::ref world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result.reference(); // returning the reference avoids the copying. + } + + python::ref world_getstate(python::tuple const & args, + python::dictionary const & keywords); + + PyObject* world_setstate(python::tuple const & args, + python::dictionary const & keywords); +} + +BOOST_PYTHON_MODULE_INIT(pickle3) +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("pickle3"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def_raw(world_getstate, "__getstate__"); + world_class.def_raw(world_setstate, "__setstate__"); + world_class.getstate_manages_dict(); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} + +namespace { + + python::ref world_getstate(python::tuple const & args, + python::dictionary const & keywords) + { + if(args.size() != 1 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + const world& w = args[0].get(); + python::ref mydict(args[0].getattr("__dict__")); + python::tuple result(2); + // store the object's __dict__ + result.set_item(0, mydict); + // store the internal state of the C++ object + result.set_item(1, w.get_secret_number()); + return result.reference(); // returning the reference avoids the copying. + } + + PyObject* world_setstate(python::tuple const & args, + python::dictionary const & keywords) + { + if(args.size() != 2 || keywords.size() != 0) { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw boost::python::argument_error(); + } + world& w = args[0].get(); + python::ref mydict(args[0].getattr("__dict__")); + const python::tuple& state(args[1].get()); + if (state.size() != 2) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + // restore the object's __dict__ + python::dictionary odict(mydict.get()); + const python::dictionary& pdict(state[0].get()); + python::list pkeys(pdict.keys()); + for (int i = 0; i < pkeys.size(); i++) { + python::ref k(pkeys[i]); + //odict[k] = pdict[k]; // XXX memory leak! + odict[k] = pdict.get_item(k); // this does not leak. + } + // restore the internal state of the C++ object + int number = state[1].get(); + if (number != 42) + w.set_secret_number(number); + return python::detail::none(); + } +} diff --git a/example/test_pickle1.py b/example/test_pickle1.py new file mode 100644 index 00000000..05696d4a --- /dev/null +++ b/example/test_pickle1.py @@ -0,0 +1,31 @@ +r'''>>> import pickle1 + >>> import re + >>> import pickle + >>> pickle1.world.__module__ + 'pickle1' + >>> pickle1.world.__safe_for_unpickling__ + 1 + >>> pickle1.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\)\)", + ... repr(pickle1.world('Hello').__reduce__())) + >>> + >>> wd = pickle1.world('California') + >>> pstr = pickle.dumps(wd) + >>> wl = pickle.loads(pstr) + >>> print wd.greet() + Hello from California! + >>> print wl.greet() + Hello from California! +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle1 + doctest.testmod(test_pickle1) + +if __name__ == '__main__': + run() diff --git a/example/test_pickle2.py b/example/test_pickle2.py new file mode 100644 index 00000000..463befa6 --- /dev/null +++ b/example/test_pickle2.py @@ -0,0 +1,45 @@ +r'''>>> import pickle2 + >>> import re + >>> import pickle + >>> pickle2.world.__module__ + 'pickle2' + >>> pickle2.world.__safe_for_unpickling__ + 1 + >>> pickle2.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\), \(0,\)\)", + ... repr(pickle2.world('Hello').__reduce__())) + >>> + >>> for number in (24, 42): + ... wd = pickle2.world('California') + ... wd.set_secret_number(number) + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number() + ... print wl.greet(), wl.get_secret_number() + Hello from California! 24 + Hello from California! 24 + Hello from California! 42 + Hello from California! 0 + +# Now show that the __dict__ is not taken care of. + >>> wd = pickle2.world('California') + >>> wd.x = 1 + >>> wd.__dict__ + {'x': 1} + >>> try: pstr = pickle.dumps(wd) + ... except RuntimeError, err: print err[0] + ... + Incomplete pickle support (__getstate_manages_dict__ not set) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle2 + doctest.testmod(test_pickle2) + +if __name__ == '__main__': + run() diff --git a/example/test_pickle3.py b/example/test_pickle3.py new file mode 100644 index 00000000..b964f1a2 --- /dev/null +++ b/example/test_pickle3.py @@ -0,0 +1,38 @@ +r'''>>> import pickle3 + >>> import re + >>> import pickle + >>> pickle3.world.__module__ + 'pickle3' + >>> pickle3.world.__safe_for_unpickling__ + 1 + >>> pickle3.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\), \(\{\}, 0\)\)", + ... repr(pickle3.world('Hello').__reduce__())) + >>> + >>> for number in (24, 42): + ... wd = pickle3.world('California') + ... wd.set_secret_number(number) + ... wd.x = 2 * number + ... wd.y = 'y' * number + ... wd.z = 3. * number + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number(), wd.__dict__ + ... print wl.greet(), wl.get_secret_number(), wl.__dict__ + Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} + Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'} +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_pickle3 + doctest.testmod(test_pickle3) + +if __name__ == '__main__': + run()