mirror of
https://github.com/boostorg/python.git
synced 2026-01-21 17:12:22 +00:00
Compare commits
11 Commits
svn-branch
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e415b5252 | ||
|
|
87288a38b5 | ||
|
|
02afd4b51d | ||
|
|
72e3420e33 | ||
|
|
2b1ffc9335 | ||
|
|
bc71b32036 | ||
|
|
c008e883ca | ||
|
|
f964a02570 | ||
|
|
edb9e11a50 | ||
|
|
414840de42 | ||
|
|
cfede0ab0e |
64
CMakeLists.txt
Normal file
64
CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
if (PYTHON_LIBRARIES)
|
||||
include_directories(${PYTHON_INCLUDE_PATH})
|
||||
|
||||
# Determine extra libraries we need to link against to build Python
|
||||
# extension modules.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "dl")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSD")
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "DragonFly")
|
||||
# DragonFly is a variant of FreeBSD
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF")
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread" "dl")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||
# No options necessary for QNX
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
# No options necessary for Mac OS X
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
|
||||
elseif(UNIX)
|
||||
# Assume -pthread and -ldl on all other variants
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread" "dl")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "util")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
|
||||
# Macro for building Boost.Python extension modules
|
||||
macro(boost_python_extension MODULE_NAME)
|
||||
parse_arguments(BPL_EXT
|
||||
""
|
||||
""
|
||||
${ARGN})
|
||||
|
||||
# Create the library target itself
|
||||
add_library(${MODULE_NAME} MODULE ${BPL_EXT_DEFAULT_ARGS} )
|
||||
|
||||
# Miscellaneous target properties
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
# Link against Boost.Python library
|
||||
target_link_libraries(${MODULE_NAME} boost_python-shared)
|
||||
|
||||
# Link against Python libraries
|
||||
target_link_libraries(${MODULE_NAME} ${PYTHON_LIBRARIES})
|
||||
endmacro(boost_python_extension)
|
||||
|
||||
boost_library_project(
|
||||
Python
|
||||
SRCDIRS src
|
||||
TESTDIRS test
|
||||
HEADERS python.hpp python
|
||||
MODULARIZED
|
||||
DESCRIPTION "A framework for interfacing Python and C++. It allows you to quickly and seamlessly expose C++ classes functions and objects to Python, and vice-versa, using no special tools -- just your C++ compiler."
|
||||
AUTHORS "David Abrahams <dave -at- boostpro.com>"
|
||||
)
|
||||
endif (PYTHON_LIBRARIES)
|
||||
@@ -9,7 +9,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="logo-boost-python-build-and-test-howto">
|
||||
<h1 class="title"><a class="reference external" href="../index.htm"><img alt="Boost C++ Libraries:" class="boost-logo" src="../../../boost.png" /></a> Boost.Python Build and Test HOWTO</h1>
|
||||
<h1 class="title"><a class="reference external" href="../index.html"><img alt="Boost C++ Libraries:" class="boost-logo" src="../../../boost.png" /></a> Boost.Python Build and Test HOWTO</h1>
|
||||
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
@@ -158,8 +158,8 @@ all the parts of your Python installation. If it isn't, consider
|
||||
<p>If you're still having trouble, Someone on one of the following
|
||||
mailing lists may be able to help:</p>
|
||||
<ul class="simple">
|
||||
<li>The <a class="reference external" href="http://www.boost.org/community/groups.html#jamboost">Boost.Build mailing list</a> for issues related to Boost.Build</li>
|
||||
<li>The Python <a class="reference external" href="http://www.boost.org/community/groups.html#cplussig">C++ Sig</a> for issues specifically related to Boost.Python</li>
|
||||
<li>The <a class="reference external" href="http://www.boost.org/more/mailing_lists.htm#jamboost">Boost.Build mailing list</a> for issues related to Boost.Build</li>
|
||||
<li>The Python <a class="reference external" href="http://www.boost.org/more/mailing_lists.htm#cplussig">C++ Sig</a> for issues specifically related to Boost.Python</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="in-case-everything-seemed-to-work">
|
||||
|
||||
@@ -177,8 +177,8 @@ mailing lists may be able to help:
|
||||
* The `Boost.Build mailing list`__ for issues related to Boost.Build
|
||||
* The Python `C++ Sig`__ for issues specifically related to Boost.Python
|
||||
|
||||
__ http://www.boost.org/community/groups.html#jamboost
|
||||
__ http://www.boost.org/community/groups.html#cplussig
|
||||
__ http://www.boost.org/more/mailing_lists.htm#jamboost
|
||||
__ http://www.boost.org/more/mailing_lists.htm#cplussig
|
||||
|
||||
In Case Everything Seemed to Work
|
||||
---------------------------------
|
||||
|
||||
@@ -375,6 +375,27 @@
|
||||
application modules, including GUI and post-processing of results.</p>
|
||||
</dd>
|
||||
|
||||
<dt><b><a href="http://polybori.sourceforge.net/">PolyBoRi</a></b></dt>
|
||||
|
||||
<dd>
|
||||
<p><a href="mailto:brickenstein@mfo.de"
|
||||
>Michael Brickenstein</a> writes:</p>
|
||||
|
||||
<blockquote>
|
||||
<p>The core of PolyBoRi is a C++ library, which provides
|
||||
high-level data types for Boolean polynomials and monomials,
|
||||
exponent vectors, as well as for the underlying polynomial
|
||||
rings and subsets of the powerset of the Boolean variables. As
|
||||
a unique approach, binary decision diagrams are used as
|
||||
internal storage type for polynomial structures. On top of
|
||||
this C++-library we provide a Python interface. This allows
|
||||
parsing of complex polynomial systems, as well as sophisticated
|
||||
and extendable strategies for Gröbner basis computation.
|
||||
Boost.Python has helped us to create this interface in a
|
||||
very clean way.</p>
|
||||
</blockquote>
|
||||
</dd>
|
||||
|
||||
<dt><b><a href="http://www.rationaldiscovery.com">Rational Discovery
|
||||
LLC</a></b></dt>
|
||||
|
||||
@@ -435,11 +456,11 @@
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
15 July, 2003</p>
|
||||
29 May, 2008</p>
|
||||
|
||||
<p><i>© Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003.</i></p>
|
||||
Abrahams</a> 2002-2008.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
</dt>
|
||||
|
||||
<dt><b><a href=
|
||||
"http://www.boost.org/community/groups.html#cplussig">The Python
|
||||
"http://www.boost.org/more/mailing_lists.htm#cplussig">The Python
|
||||
C++-sig</a></b> mailing list is a forum for discussing Python/C++
|
||||
interoperability, and Boost.Python in particular. Post your
|
||||
Boost.Python questions here.<br>
|
||||
|
||||
@@ -93,7 +93,7 @@ who had to use a different tool.
|
||||
|
||||
We will skip over the details. Our objective will be to simply create
|
||||
the hello world module and run it in Python. For a complete reference to
|
||||
building Boost.Python, check out: [@/libs/python/doc/building.html
|
||||
building Boost.Python, check out: [@../../../building.html
|
||||
building.html]. After this brief ['bjam] tutorial, we should have built
|
||||
the DLLs and run a python program using the extension.
|
||||
|
||||
@@ -118,7 +118,7 @@ platforms. The complete list of Bjam executables can be found
|
||||
[h2 Let's Jam!]
|
||||
__jam__
|
||||
|
||||
[@/libs/python/example/tutorial/Jamroot Here] is our minimalist Jamroot
|
||||
[@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot
|
||||
file. Simply copy the file and tweak [^use-project boost] to where your
|
||||
boost root directory is and your OK.
|
||||
|
||||
@@ -186,6 +186,10 @@ And so on... Finally:
|
||||
Or something similar. If all is well, you should now have built the DLLs and
|
||||
run the Python program.
|
||||
|
||||
[note Starting from Boost 1.35, bjam erases the generated executables
|
||||
(e.g. pyd file) after the test has concluded to conserve disk space.
|
||||
To keep bjam from doing that, pass --preserve-test-targets to bjam.]
|
||||
|
||||
[:[*There you go... Have fun!]]
|
||||
|
||||
[endsect]
|
||||
@@ -463,7 +467,7 @@ functions so that a Python override may be called:
|
||||
};
|
||||
|
||||
Notice too that in addition to inheriting from `Base`, we also multiply-
|
||||
inherited `wrapper<Base>` (See [@/libs/python/doc/v2/wrapper.html Wrapper]). The
|
||||
inherited `wrapper<Base>` (See [@../../../v2/wrapper.html Wrapper]). The
|
||||
`wrapper` template makes the job of wrapping classes that are meant to
|
||||
overridden in Python, easier.
|
||||
|
||||
@@ -495,7 +499,7 @@ Methods correspond roughly to C++'s [*member functions]]
|
||||
[section Virtual Functions with Default Implementations]
|
||||
|
||||
We've seen in the previous section how classes with pure virtual functions are
|
||||
wrapped using Boost.Python's [@/libs/python/doc/v2/wrapper.html class wrapper]
|
||||
wrapped using Boost.Python's [@../../../v2/wrapper.html class wrapper]
|
||||
facilities. If we wish to wrap [*non]-pure-virtual functions instead, the
|
||||
mechanism is a bit different.
|
||||
|
||||
@@ -812,7 +816,7 @@ or more policies can be composed by chaining. Here's the general syntax:
|
||||
policy3<args...> > >
|
||||
|
||||
Here is the list of predefined call policies. A complete reference detailing
|
||||
these can be found [@/libs/python/doc/v2/reference.html#models_of_call_policies here].
|
||||
these can be found [@../../../v2/reference.html#models_of_call_policies here].
|
||||
|
||||
* [*with_custodian_and_ward]: Ties lifetimes of the arguments
|
||||
* [*with_custodian_and_ward_postcall]: Ties lifetimes of the arguments and results
|
||||
@@ -970,7 +974,7 @@ fourth macro argument). The thin wrappers are all enclosed in a class named
|
||||
|
||||
.def("wack_em", &george::wack_em, george_overloads());
|
||||
|
||||
See the [@/libs/python/doc/v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference]
|
||||
See the [@../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference]
|
||||
for details.
|
||||
|
||||
[h2 init and optional]
|
||||
@@ -1267,7 +1271,7 @@ associated with the C++ type passed as its first parameter.
|
||||
The scope is a class that has an associated global Python object which
|
||||
controls the Python namespace in which new extension classes and wrapped
|
||||
functions will be defined as attributes. Details can be found
|
||||
[@/libs/python/doc/v2/scope.html here].]
|
||||
[@../../../v2/scope.html here].]
|
||||
|
||||
You can access those values in Python as
|
||||
|
||||
@@ -1328,7 +1332,7 @@ in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the
|
||||
variants are called [^boost_python.lib] (for release builds) and
|
||||
[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
|
||||
you probably haven't built Boost.Python yet. See
|
||||
[@/libs/python/doc/building.html Building and Testing] on how to do this.
|
||||
[@../../../building.html Building and Testing] on how to do this.
|
||||
|
||||
Python's library can be found in the [^/libs] subdirectory of
|
||||
your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
@@ -1386,8 +1390,8 @@ There is a difference however. While the reference-counting is fully
|
||||
automatic in Python, the Python\/C API requires you to do it
|
||||
[@http://www.python.org/doc/current/api/refcounts.html by hand]. This is
|
||||
messy and especially hard to get right in the presence of C++ exceptions.
|
||||
Fortunately Boost.Python provides the [@/libs/python/doc/v2/handle.html handle] and
|
||||
[@/libs/python/doc/v2/object.html object] class templates to automate the process.
|
||||
Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
|
||||
[@../../../v2/object.html object] class templates to automate the process.
|
||||
|
||||
[h2 Running Python code]
|
||||
|
||||
@@ -1450,7 +1454,7 @@ which returns the result directly:
|
||||
[h2 Exception handling]
|
||||
|
||||
If an exception occurs in the evaluation of the python expression,
|
||||
[@/libs/python/doc/v2/errors.html#error_already_set-spec error_already_set] is thrown:
|
||||
[@../../../v2/errors.html#error_already_set-spec error_already_set] is thrown:
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1954,13 +1958,13 @@ This method is recommended too if you are developing the C++ library and
|
||||
exporting it to Python at the same time: changes in a class will only demand
|
||||
the compilation of a single cpp, instead of the entire wrapper code.
|
||||
|
||||
[note If you're exporting your classes with [@/libs/python/doc/pyste/index.html Pyste],
|
||||
[note If you're exporting your classes with [@../../../../pyste/index.html Pyste],
|
||||
take a look at the [^--multiple] option, that generates the wrappers in
|
||||
various files as demonstrated here.]
|
||||
|
||||
[note This method is useful too if you are getting the error message
|
||||
['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling
|
||||
a large source file, as explained in the [@/libs/python/doc/v2/faq.html#c1204 FAQ].]
|
||||
a large source file, as explained in the [@../../../v2/faq.html#c1204 FAQ].]
|
||||
|
||||
[endsect]
|
||||
[endsect] [/ General Techniques]
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
<td valign="top"><code>P::extract_return_type</code></td>
|
||||
|
||||
<td>A model of <a href=
|
||||
"../../../doc/refmanual/metafunction.html">Metafunction</a>.</td>
|
||||
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a>.</td>
|
||||
|
||||
<td>An MPL unary <a href=
|
||||
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a> used extract the return type from a given signature. By default it is derived from mpl::front.</td>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href=../../../../boost.css>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
<title>Boost.Python - Dereferenceable Concept</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href=../../../../boost.css>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
<title>Boost.Python - Extractor Concept</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href=../../../../boost.css>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
<title>Boost.Python - Holder Concept</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
|
||||
@@ -74,6 +74,32 @@
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#const_objattribute_policies-spec">Class
|
||||
<code>const_objattribute_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#const_objattribute_policies-spec-synopsis">Class
|
||||
<code>const_objattribute_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#const_objattribute_policies-spec-statics">Class
|
||||
<code>const_objattribute_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#objattribute_policies-spec">Class
|
||||
<code>objattribute_policies</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#objattribute_policies-spec-synopsis">Class
|
||||
<code>objattribute_policies</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#objattribute_policies-spec-statics">Class
|
||||
<code>objattribute_policies</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#const_item_policies-spec">Class
|
||||
<code>const_item_policies</code></a></dt>
|
||||
|
||||
@@ -328,6 +354,102 @@ static void del(object const&target, char const* key);
|
||||
<!-- end -->
|
||||
<!-- begin -->
|
||||
|
||||
<h3><a name="const_objattribute_policies-spec"></a>Class
|
||||
<code>const_objattribute_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an attribute
|
||||
access to a <code>const object</code> when the attribute name is
|
||||
given as a <code>const object</code>.</p>
|
||||
|
||||
<h4><a name="const_objattribute_policies-spec-synopsis"></a>Class
|
||||
<code>const_objattribute_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct const_objattribute_policies
|
||||
{
|
||||
typedef object const& key_type;
|
||||
static object get(object const& target, object const& key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="const_objattribute_policies-spec-statics"></a>Class
|
||||
<code>const_objattribute_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object get(object const& target, object const& key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>key</code> is an <code>object</code>
|
||||
holding a string.</dt>
|
||||
|
||||
<dt><b>Effects:</b> accesses the attribute of <code>target</code> named
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> An <code>object</code> managing the result of the
|
||||
attribute access.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="objattribute_policies-spec"></a>Class
|
||||
<code>objattribute_policies</code></h3>
|
||||
|
||||
<p>The policies which are used for proxies representing an attribute
|
||||
access to a mutable <code>object</code> when the attribute name is
|
||||
given as a <code>const object</code>.</p>
|
||||
|
||||
<h4><a name="objattribute_policies-spec-synopsis"></a>Class
|
||||
<code>objattribute_policies</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace api
|
||||
{
|
||||
struct objattribute_policies : const_objattribute_policies
|
||||
{
|
||||
static object const& set(object const& target, object const& key, object const& value);
|
||||
static void del(object const&target, object const& key);
|
||||
};
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="objattribute_policies-spec-statics"></a>Class
|
||||
<code>objattribute_policies</code> static functions</h4>
|
||||
<pre>
|
||||
static object const& set(object const& target, object const& key, object const& value);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>key</code> is an <code>object</code>
|
||||
holding a string.</dt>
|
||||
|
||||
<dt><b>Effects:</b> sets the attribute of <code>target</code> named by
|
||||
<code>key</code> to <code>value</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
static void del(object const&target, object const& key);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>key</code> is an <code>object</code>
|
||||
holding a string.</dt>
|
||||
|
||||
<dt><b>Effects:</b> deletes the attribute of <code>target</code> named
|
||||
by <code>key</code>.</dt>
|
||||
|
||||
<dt><b>Throws:</b> <code><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></code> if a
|
||||
Python exception is raised.</dt>
|
||||
</dl>
|
||||
<!-- end -->
|
||||
<!-- begin -->
|
||||
|
||||
<h3><a name="const_item_policies-spec"></a>Class
|
||||
<code>const_item_policies</code></h3>
|
||||
|
||||
@@ -533,6 +655,11 @@ namespace boost { namespace python { namespace api
|
||||
template <class A0, class A1,...class An>
|
||||
object operator()(A0 const&, A1 const&,...An const&) const;
|
||||
|
||||
detail::args_proxy operator* () const;
|
||||
object operator()(detail::args_proxy const &args) const;
|
||||
object operator()(detail::args_proxy const &args,
|
||||
detail::kwds_proxy const &kwds) const;
|
||||
|
||||
// truth value testing
|
||||
//
|
||||
typedef unspecified bool_type;
|
||||
@@ -542,6 +669,8 @@ namespace boost { namespace python { namespace api
|
||||
//
|
||||
proxy<const_object_attribute> attr(char const*) const;
|
||||
proxy<object_attribute> attr(char const*);
|
||||
proxy<const_object_objattribute> attr(object const&) const;
|
||||
proxy<object_objattribute> attr(object const&);
|
||||
|
||||
// item access
|
||||
//
|
||||
@@ -580,6 +709,25 @@ object operator()(A0 const& a1, A1 const& a2,...An const& aN) const;
|
||||
call<object>(object(*static_cast<U*>(this)).ptr(), a1,
|
||||
a2,...aN)</dt>
|
||||
</dl>
|
||||
|
||||
<pre>
|
||||
object operator()(detail::args_proxy const &args) const;
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
call object with arguments given by the tuple <varname>args</varname></dt>
|
||||
</dl>
|
||||
<pre>
|
||||
object operator()(detail::args_proxy const &args,
|
||||
detail::kwds_proxy const &kwds) const;
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
call object with arguments given by the tuple <varname>args</varname>, and named
|
||||
arguments given by the dictionary <varname>kwds</varname></dt>
|
||||
</dl>
|
||||
|
||||
|
||||
<pre>
|
||||
operator bool_type() const;
|
||||
</pre>
|
||||
@@ -608,6 +756,21 @@ proxy<object_attribute> attr(char const* name);
|
||||
<code>name</code> as its key.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
proxy<const_object_objattribute> attr(const object& name) const;
|
||||
proxy<object_objattribute> attr(const object& name);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> name is a <code>object</code> holding a string.</dt>
|
||||
|
||||
<dt><b>Effects:</b> accesses the named attribute of
|
||||
<code>*this</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> a proxy object which binds
|
||||
<code>object(*static_cast<U*>(this))</code> as its target, and
|
||||
<code>name</code> as its key.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class T>
|
||||
proxy<const_object_item> operator[](T const& key) const;
|
||||
template <class T>
|
||||
@@ -938,11 +1101,11 @@ object sum_items(object seq)
|
||||
</pre>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 January, 2006
|
||||
27 May, 2008
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2006.</i></p>
|
||||
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2008.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,112 +1,93 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<title>Boost.Python Pickle Support</title>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Boost.Python Pickle Support</title>
|
||||
</head>
|
||||
|
||||
<div>
|
||||
<body>
|
||||
<div>
|
||||
<img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
||||
"center" width="277" height="86" />
|
||||
<hr />
|
||||
|
||||
<img src="../../../../boost.png"
|
||||
alt="boost.png (6897 bytes)"
|
||||
align="center"
|
||||
width="277" height="86">
|
||||
<h1>Boost.Python Pickle Support</h1>Pickle is a Python module for object
|
||||
serialization, also known as persistence, marshalling, or flattening.
|
||||
|
||||
<hr>
|
||||
<h1>Boost.Python Pickle Support</h1>
|
||||
<p>It is often necessary to save and restore the contents of an object to
|
||||
a file. One approach to this problem is to write a pair of functions that
|
||||
read and write data from a file in a special format. A powerful
|
||||
alternative approach is to use Python's pickle module. Exploiting
|
||||
Python's ability for introspection, the pickle module recursively
|
||||
converts nearly arbitrary Python objects into a stream of bytes that can
|
||||
be written to a file.</p>
|
||||
|
||||
Pickle is a Python module for object serialization, also known
|
||||
as persistence, marshalling, or flattening.
|
||||
<p>The Boost Python Library supports the pickle module through the
|
||||
interface as described in detail in the <a href=
|
||||
"http://www.python.org/doc/current/lib/module-pickle.html">Python Library
|
||||
Reference for pickle.</a> This interface involves the special methods
|
||||
<tt>__getinitargs__</tt>, <tt>__getstate__</tt> and <tt>__setstate__</tt>
|
||||
as described in the following. Note that Boost.Python is also fully
|
||||
compatible with Python's cPickle module.</p>
|
||||
<hr />
|
||||
|
||||
<p>
|
||||
It is often necessary to save and restore the contents of an object to
|
||||
a file. One approach to this problem is to write a pair of functions
|
||||
that read and write data from a file in a special format. A powerful
|
||||
alternative approach is to use Python's pickle module. Exploiting
|
||||
Python's ability for introspection, the pickle module recursively
|
||||
converts nearly arbitrary Python objects into a stream of bytes that
|
||||
can be written to a file.
|
||||
<h2>The Boost.Python Pickle Interface</h2>At the user level, the
|
||||
Boost.Python pickle interface involves three special methods:
|
||||
|
||||
<p>
|
||||
The Boost Python Library supports the pickle module
|
||||
through the interface as described in detail in the
|
||||
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
|
||||
>Python Library Reference for pickle.</a> This interface
|
||||
involves the special methods <tt>__getinitargs__</tt>,
|
||||
<tt>__getstate__</tt> and <tt>__setstate__</tt> as described
|
||||
in the following. Note that Boost.Python is also fully compatible
|
||||
with Python's cPickle module.
|
||||
<dl>
|
||||
<dt><strong><tt>__getinitargs__</tt></strong></dt>
|
||||
|
||||
<hr>
|
||||
<h2>The Boost.Python Pickle Interface</h2>
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is pickled, the
|
||||
pickler tests if the instance has a <tt>__getinitargs__</tt> 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.
|
||||
|
||||
At the user level, the Boost.Python pickle interface involves three special
|
||||
methods:
|
||||
<p>If <tt>__getinitargs__</tt> is not defined, <tt>pickle.load</tt>
|
||||
will call the constructor (<tt>__init__</tt>) without arguments;
|
||||
i.e., the object must be default-constructible.</p>
|
||||
</dd>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<strong><tt>__getinitargs__</tt></strong>
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is pickled, the
|
||||
pickler tests if the instance has a <tt>__getinitargs__</tt> 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.
|
||||
<dt><strong><tt>__getstate__</tt></strong></dt>
|
||||
|
||||
<p>
|
||||
If <tt>__getinitargs__</tt> is not defined, <tt>pickle.load</tt>
|
||||
will call the constructor (<tt>__init__</tt>) without arguments;
|
||||
i.e., the object must be default-constructible.
|
||||
<dd>When an instance of a Boost.Python extension class is pickled, the
|
||||
pickler tests if the instance has a <tt>__getstate__</tt> method. This
|
||||
method should return a Python object representing the state of the
|
||||
instance.</dd>
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong><tt>__getstate__</tt></strong>
|
||||
<dt><strong><tt>__setstate__</tt></strong></dt>
|
||||
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is pickled, the
|
||||
pickler tests if the instance has a <tt>__getstate__</tt> method.
|
||||
This method should return a Python object representing the state of
|
||||
the instance.
|
||||
<dd>When an instance of a Boost.Python extension class is restored by
|
||||
the unpickler (<tt>pickle.load</tt>), it is first constructed using the
|
||||
result of <tt>__getinitargs__</tt> as arguments (see above).
|
||||
Subsequently the unpickler tests if the new instance has a
|
||||
<tt>__setstate__</tt> method. If so, this method is called with the
|
||||
result of <tt>__getstate__</tt> (a Python object) as the argument.</dd>
|
||||
</dl>The three special methods described above may be <tt>.def()</tt>'ed
|
||||
individually by the user. However, Boost.Python provides an easy to use
|
||||
high-level interface via the
|
||||
<strong><tt>boost::python::pickle_suite</tt></strong> class that also
|
||||
enforces consistency: <tt>__getstate__</tt> and <tt>__setstate__</tt>
|
||||
must be defined as pairs. Use of this interface is demonstrated by the
|
||||
following examples.
|
||||
<hr />
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong><tt>__setstate__</tt></strong>
|
||||
<h2>Examples</h2>There are three files in <tt>boost/libs/python/test</tt>
|
||||
that show how to provide pickle support.
|
||||
<hr />
|
||||
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is restored by the
|
||||
unpickler (<tt>pickle.load</tt>), it is first constructed using the
|
||||
result of <tt>__getinitargs__</tt> as arguments (see above). Subsequently
|
||||
the unpickler tests if the new instance has a <tt>__setstate__</tt>
|
||||
method. If so, this method is called with the result of
|
||||
<tt>__getstate__</tt> (a Python object) as the argument.
|
||||
<h3><a href="../../test/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>The C++
|
||||
class in this example can be fully restored by passing the appropriate
|
||||
argument to the constructor. Therefore it is sufficient to define the
|
||||
pickle interface method <tt>__getinitargs__</tt>. This is done in the
|
||||
following way:
|
||||
|
||||
</dl>
|
||||
|
||||
The three special methods described above may be <tt>.def()</tt>'ed
|
||||
individually by the user. However, Boost.Python provides an easy to use
|
||||
high-level interface via the
|
||||
<strong><tt>boost::python::pickle_suite</tt></strong> class that also
|
||||
enforces consistency: <tt>__getstate__</tt> and <tt>__setstate__</tt>
|
||||
must be defined as pairs. Use of this interface is demonstrated by the
|
||||
following examples.
|
||||
|
||||
<hr>
|
||||
<h2>Examples</h2>
|
||||
|
||||
There are three files in
|
||||
<tt>boost/libs/python/test</tt> that show how to
|
||||
provide pickle support.
|
||||
|
||||
<hr>
|
||||
<h3><a href="../../test/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>
|
||||
|
||||
The C++ class in this example can be fully restored by passing the
|
||||
appropriate argument to the constructor. Therefore it is sufficient
|
||||
to define the pickle interface method <tt>__getinitargs__</tt>.
|
||||
This is done in the following way:
|
||||
|
||||
<ul>
|
||||
<li>1. Definition of the C++ pickle function:
|
||||
<pre>
|
||||
<ul>
|
||||
<li>1. Definition of the C++ pickle function:
|
||||
<pre>
|
||||
struct world_pickle_suite : boost::python::pickle_suite
|
||||
{
|
||||
static
|
||||
@@ -117,26 +98,28 @@ provide pickle support.
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<li>2. Establishing the Python binding:
|
||||
<pre>
|
||||
</li>
|
||||
|
||||
<li>2. Establishing the Python binding:
|
||||
<pre>
|
||||
class_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.def_pickle(world_pickle_suite())
|
||||
// ...
|
||||
</pre>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<hr />
|
||||
|
||||
<hr>
|
||||
<h3><a href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>
|
||||
<h3><a href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>The C++
|
||||
class in this example contains member data that cannot be restored by any
|
||||
of the constructors. Therefore it is necessary to provide the
|
||||
<tt>__getstate__</tt>/<tt>__setstate__</tt> pair of pickle interface
|
||||
methods:
|
||||
|
||||
The C++ class in this example contains member data that cannot be
|
||||
restored by any of the constructors. Therefore it is necessary to
|
||||
provide the <tt>__getstate__</tt>/<tt>__setstate__</tt> pair of
|
||||
pickle interface methods:
|
||||
|
||||
<ul>
|
||||
<li>1. Definition of the C++ pickle functions:
|
||||
<pre>
|
||||
<ul>
|
||||
<li>1. Definition of the C++ pickle functions:
|
||||
<pre>
|
||||
struct world_pickle_suite : boost::python::pickle_suite
|
||||
{
|
||||
static
|
||||
@@ -161,92 +144,76 @@ provide pickle support.
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<li>2. Establishing the Python bindings for the entire suite:
|
||||
<pre>
|
||||
</li>
|
||||
|
||||
<li>2. Establishing the Python bindings for the entire suite:
|
||||
<pre>
|
||||
class_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.def_pickle(world_pickle_suite())
|
||||
// ...
|
||||
</pre>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
For simplicity, the <tt>__dict__</tt> is not included in the result
|
||||
of <tt>__getstate__</tt>. This is not generally recommended, but a
|
||||
valid approach if it is anticipated that the object's
|
||||
<tt>__dict__</tt> will always be empty. Note that the safety guard
|
||||
described below will catch the cases where this assumption is violated.
|
||||
<p>For simplicity, the <tt>__dict__</tt> is not included in the result of
|
||||
<tt>__getstate__</tt>. This is not generally recommended, but a valid
|
||||
approach if it is anticipated that the object's <tt>__dict__</tt> will
|
||||
always be empty. Note that the safety guard described below will catch
|
||||
the cases where this assumption is violated.</p>
|
||||
<hr />
|
||||
|
||||
<hr>
|
||||
<h3><a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>
|
||||
<h3><a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>This
|
||||
example is similar to <a href=
|
||||
"../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the object's
|
||||
<tt>__dict__</tt> is included in the result of <tt>__getstate__</tt>.
|
||||
This requires a little more code but is unavoidable if the object's
|
||||
<tt>__dict__</tt> is not always empty.
|
||||
<hr />
|
||||
|
||||
This example is similar to <a
|
||||
href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the
|
||||
object's <tt>__dict__</tt> is included in the result of
|
||||
<tt>__getstate__</tt>. This requires a little more code but is
|
||||
unavoidable if the object's <tt>__dict__</tt> is not always empty.
|
||||
<h2>Pitfall and Safety Guard</h2>The pickle protocol described above has
|
||||
an important pitfall that the end user of a Boost.Python extension module
|
||||
might not be aware of:
|
||||
|
||||
<hr>
|
||||
<h2>Pitfall and Safety Guard</h2>
|
||||
<p><strong><tt>__getstate__</tt> is defined and the instance's
|
||||
<tt>__dict__</tt> is not empty.</strong></p>
|
||||
|
||||
The pickle protocol described above has an important pitfall that the
|
||||
end user of a Boost.Python extension module might not be aware of:
|
||||
<p>
|
||||
<strong>
|
||||
<tt>__getstate__</tt> is defined and the instance's <tt>__dict__</tt>
|
||||
is not empty.
|
||||
</strong>
|
||||
<p>
|
||||
<p>The author of a Boost.Python extension class might provide a
|
||||
<tt>__getstate__</tt> method without considering the possibilities
|
||||
that:</p>
|
||||
|
||||
The author of a Boost.Python extension class might provide a
|
||||
<tt>__getstate__</tt> method without considering the possibilities
|
||||
that:
|
||||
<ul>
|
||||
<li>his class is used in Python as a base class. Most likely the
|
||||
<tt>__dict__</tt> of instances of the derived class needs to be pickled
|
||||
in order to restore the instances correctly.</li>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
his class is used in Python as a base class. Most likely the
|
||||
<tt>__dict__</tt> of instances of the derived class needs to be
|
||||
pickled in order to restore the instances correctly.
|
||||
<li>the user adds items to the instance's <tt>__dict__</tt> directly.
|
||||
Again, the <tt>__dict__</tt> of the instance then needs to be
|
||||
pickled.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<li>
|
||||
the user adds items to the instance's <tt>__dict__</tt> directly.
|
||||
Again, the <tt>__dict__</tt> of the instance then needs to be
|
||||
pickled.
|
||||
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
To alert the user to this highly unobvious problem, a safety guard is
|
||||
provided. If <tt>__getstate__</tt> is defined and the instance's
|
||||
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has
|
||||
an attribute <tt>__getstate_manages_dict__</tt>. An exception is
|
||||
raised if this attribute is not defined:
|
||||
|
||||
<pre>
|
||||
<p>To alert the user to this highly unobvious problem, a safety guard is
|
||||
provided. If <tt>__getstate__</tt> is defined and the instance's
|
||||
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has an
|
||||
attribute <tt>__getstate_manages_dict__</tt>. An exception is raised if
|
||||
this attribute is not defined:</p>
|
||||
<pre>
|
||||
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
|
||||
</pre>
|
||||
|
||||
To resolve this problem, it should first be established that the
|
||||
<tt>__getstate__</tt> and <tt>__setstate__</tt> methods manage the
|
||||
instances's <tt>__dict__</tt> correctly. Note that this can be done
|
||||
either at the C++ or the Python level. Finally, the safety guard
|
||||
should intentionally be overridden. E.g. in C++ (from
|
||||
<a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a>):
|
||||
|
||||
<pre>
|
||||
</pre>To resolve this problem, it should first be established that the <tt>
|
||||
__getstate__</tt> and <tt>__setstate__</tt> methods manage the
|
||||
instances's <tt>__dict__</tt> correctly. Note that this can be done
|
||||
either at the C++ or the Python level. Finally, the safety guard should
|
||||
intentionally be overridden. E.g. in C++ (from <a href=
|
||||
"../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a>):
|
||||
<pre>
|
||||
struct world_pickle_suite : boost::python::pickle_suite
|
||||
{
|
||||
// ...
|
||||
|
||||
static bool getstate_manages_dict() { return true; }
|
||||
};
|
||||
</pre>
|
||||
|
||||
Alternatively in Python:
|
||||
|
||||
<pre>
|
||||
</pre>Alternatively in Python:
|
||||
<pre>
|
||||
import your_bpl_module
|
||||
class your_class(your_bpl_module.your_class):
|
||||
__getstate_manages_dict__ = 1
|
||||
@@ -255,54 +222,41 @@ is not empty.
|
||||
def __setstate__(self, state):
|
||||
# your code here
|
||||
</pre>
|
||||
<hr />
|
||||
|
||||
<hr>
|
||||
<h2>Practical Advice</h2>
|
||||
<h2>Practical Advice</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
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.
|
||||
<ul>
|
||||
<li>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.</li>
|
||||
|
||||
<p>
|
||||
<li>
|
||||
Avoid using <tt>__getstate__</tt> if the instance can also be
|
||||
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
|
||||
avoids the pitfall described above.
|
||||
<li>Avoid using <tt>__getstate__</tt> if the instance can also be
|
||||
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
|
||||
avoids the pitfall described above.</li>
|
||||
|
||||
<p>
|
||||
<li>
|
||||
If <tt>__getstate__</tt> is required, include the instance's
|
||||
<tt>__dict__</tt> in the Python object that is returned.
|
||||
<li>If <tt>__getstate__</tt> is required, include the instance's
|
||||
<tt>__dict__</tt> in the Python object that is returned.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
|
||||
</ul>
|
||||
<h2>Light-weight alternative: pickle support implemented in Python</h2>
|
||||
|
||||
<hr>
|
||||
<h2>Light-weight alternative: pickle support implemented in Python</h2>
|
||||
|
||||
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>
|
||||
|
||||
The <tt>pickle4.cpp</tt> example demonstrates an alternative technique
|
||||
for implementing pickle support. First we direct Boost.Python via
|
||||
the <tt>class_::enable_pickling()</tt> member function to define only
|
||||
the basic attributes required for pickling:
|
||||
|
||||
<pre>
|
||||
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>The
|
||||
<tt>pickle4.cpp</tt> example demonstrates an alternative technique for
|
||||
implementing pickle support. First we direct Boost.Python via the
|
||||
<tt>class_::enable_pickling()</tt> member function to define only the
|
||||
basic attributes required for pickling:
|
||||
<pre>
|
||||
class_<world>("world", args<const std::string&>())
|
||||
// ...
|
||||
.enable_pickling()
|
||||
// ...
|
||||
</pre>
|
||||
|
||||
This enables the standard Python pickle interface as described
|
||||
in the Python documentation. By "injecting" a
|
||||
<tt>__getinitargs__</tt> method into the definition of the wrapped
|
||||
class we make all instances pickleable:
|
||||
|
||||
<pre>
|
||||
</pre>This enables the standard Python pickle interface as described in the
|
||||
Python documentation. By "injecting" a <tt>__getinitargs__</tt> method into
|
||||
the definition of the wrapped class we make all instances pickleable:
|
||||
<pre>
|
||||
# import the wrapped world class
|
||||
from pickle4_ext import world
|
||||
|
||||
@@ -312,18 +266,15 @@ class we make all instances pickleable:
|
||||
|
||||
# now inject __getinitargs__ (Python is a dynamic language!)
|
||||
world.__getinitargs__ = world_getinitargs
|
||||
</pre>
|
||||
</pre>See also the <a href=
|
||||
"../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python">
|
||||
tutorial section</a> on injecting additional methods from Python.
|
||||
<hr />
|
||||
© Copyright Ralf W. Grosse-Kunstleve 2001-2004. Distributed under the
|
||||
Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
See also the
|
||||
<a href="../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python"
|
||||
>tutorial section</a> on injecting additional methods from Python.
|
||||
|
||||
<hr>
|
||||
|
||||
© Copyright Ralf W. Grosse-Kunstleve 2001-2004. Distributed under
|
||||
the Boost Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
<p>
|
||||
Updated: Feb 2004.
|
||||
</div>
|
||||
<p>Updated: Feb 2004.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -38,7 +38,10 @@ namespace boost { namespace python {
|
||||
|
||||
# endif // CALL_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, call.hpp)
|
||||
@@ -76,4 +79,5 @@ call(PyObject* callable
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,10 @@ namespace boost { namespace python {
|
||||
|
||||
# endif // CALL_METHOD_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
|
||||
@@ -76,4 +79,5 @@ call_method(PyObject* self, char const* name
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif // BOOST_PP_IS_ITERATING
|
||||
|
||||
@@ -86,7 +86,10 @@ result(X const&, short = 0) { return 0; }
|
||||
# endif // RESULT_DWA2002521_HPP
|
||||
|
||||
/* --------------- function pointers --------------- */
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, result.hpp(function pointers))
|
||||
@@ -128,4 +131,5 @@ boost::type<R>* result(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q, int = 0)
|
||||
# undef N
|
||||
# undef Q
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,10 @@ T& (* target(R (T::*)) )() { return 0; }
|
||||
# endif // TARGET_DWA2002521_HPP
|
||||
|
||||
/* --------------- function pointers --------------- */
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers))
|
||||
@@ -79,4 +82,5 @@ T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )()
|
||||
# undef N
|
||||
# undef Q
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,10 @@ template <int nargs> struct make_holder;
|
||||
|
||||
# endif // MAKE_HOLDER_DWA20011215_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, make_holder.hpp)
|
||||
@@ -102,4 +105,5 @@ struct make_holder<N>
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif
|
||||
|
||||
@@ -170,7 +170,10 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool
|
||||
# endif // POINTER_HOLDER_DWA20011215_HPP
|
||||
|
||||
/* --------------- pointer_holder --------------- */
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp)
|
||||
@@ -212,4 +215,5 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif
|
||||
|
||||
@@ -117,7 +117,10 @@ void* value_holder_back_reference<Value,Held>::holds(
|
||||
|
||||
// --------------- value_holder ---------------
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder))
|
||||
@@ -163,4 +166,5 @@ void* value_holder_back_reference<Value,Held>::holds(
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,7 @@ struct const_attribute_policies
|
||||
{
|
||||
typedef char const* key_type;
|
||||
static object get(object const& target, char const* key);
|
||||
static object get(object const& target, object const& key);
|
||||
};
|
||||
|
||||
struct attribute_policies : const_attribute_policies
|
||||
@@ -25,6 +26,18 @@ struct attribute_policies : const_attribute_policies
|
||||
static void del(object const&target, char const* key);
|
||||
};
|
||||
|
||||
struct const_objattribute_policies
|
||||
{
|
||||
typedef object const key_type;
|
||||
static object get(object const& target, object const& key);
|
||||
};
|
||||
|
||||
struct objattribute_policies : const_objattribute_policies
|
||||
{
|
||||
static object const& set(object const& target, object const& key, object const& value);
|
||||
static void del(object const&target, object const& key);
|
||||
};
|
||||
|
||||
//
|
||||
// implementation
|
||||
//
|
||||
@@ -42,11 +55,30 @@ inline const_object_attribute object_operators<U>::attr(char const* name) const
|
||||
return const_object_attribute(x, name);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline object_objattribute object_operators<U>::attr(object const& name)
|
||||
{
|
||||
object_cref2 x = *static_cast<U*>(this);
|
||||
return object_objattribute(x, name);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline const_object_objattribute object_operators<U>::attr(object const& name) const
|
||||
{
|
||||
object_cref2 x = *static_cast<U const*>(this);
|
||||
return const_object_objattribute(x, name);
|
||||
}
|
||||
|
||||
inline object const_attribute_policies::get(object const& target, char const* key)
|
||||
{
|
||||
return python::getattr(target, key);
|
||||
}
|
||||
|
||||
inline object const_objattribute_policies::get(object const& target, object const& key)
|
||||
{
|
||||
return python::getattr(target, key);
|
||||
}
|
||||
|
||||
inline object const& attribute_policies::set(
|
||||
object const& target
|
||||
, char const* key
|
||||
@@ -56,6 +88,15 @@ inline object const& attribute_policies::set(
|
||||
return value;
|
||||
}
|
||||
|
||||
inline object const& objattribute_policies::set(
|
||||
object const& target
|
||||
, object const& key
|
||||
, object const& value)
|
||||
{
|
||||
python::setattr(target, key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline void attribute_policies::del(
|
||||
object const& target
|
||||
, char const* key)
|
||||
@@ -63,6 +104,13 @@ inline void attribute_policies::del(
|
||||
python::delattr(target, key);
|
||||
}
|
||||
|
||||
inline void objattribute_policies::del(
|
||||
object const& target
|
||||
, object const& key)
|
||||
{
|
||||
python::delattr(target, key);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::api
|
||||
|
||||
#endif // OBJECT_ATTRIBUTES_DWA2002615_HPP
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class kwds_proxy;
|
||||
class args_proxy;
|
||||
}
|
||||
|
||||
namespace converter
|
||||
{
|
||||
template <class T> struct arg_to_python;
|
||||
@@ -59,6 +65,8 @@ namespace api
|
||||
|
||||
struct const_attribute_policies;
|
||||
struct attribute_policies;
|
||||
struct const_objattribute_policies;
|
||||
struct objattribute_policies;
|
||||
struct const_item_policies;
|
||||
struct item_policies;
|
||||
struct const_slice_policies;
|
||||
@@ -67,6 +75,8 @@ namespace api
|
||||
|
||||
typedef proxy<const_attribute_policies> const_object_attribute;
|
||||
typedef proxy<attribute_policies> object_attribute;
|
||||
typedef proxy<const_objattribute_policies> const_object_objattribute;
|
||||
typedef proxy<objattribute_policies> object_objattribute;
|
||||
typedef proxy<const_item_policies> const_object_item;
|
||||
typedef proxy<item_policies> object_item;
|
||||
typedef proxy<const_slice_policies> const_object_slice;
|
||||
@@ -98,6 +108,11 @@ namespace api
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
detail::args_proxy operator* () const;
|
||||
object operator()(detail::args_proxy const &args) const;
|
||||
object operator()(detail::args_proxy const &args,
|
||||
detail::kwds_proxy const &kwds) const;
|
||||
|
||||
// truth value testing
|
||||
//
|
||||
@@ -108,6 +123,8 @@ namespace api
|
||||
//
|
||||
const_object_attribute attr(char const*) const;
|
||||
object_attribute attr(char const*);
|
||||
const_object_objattribute attr(object const&) const;
|
||||
object_objattribute attr(object const&);
|
||||
|
||||
// item access
|
||||
//
|
||||
@@ -213,11 +230,11 @@ namespace api
|
||||
inline object_base(object_base const&);
|
||||
inline object_base(PyObject* ptr);
|
||||
|
||||
object_base& operator=(object_base const& rhs);
|
||||
~object_base();
|
||||
inline object_base& operator=(object_base const& rhs);
|
||||
inline ~object_base();
|
||||
|
||||
// Underlying object access -- returns a borrowed reference
|
||||
PyObject* ptr() const;
|
||||
inline PyObject* ptr() const;
|
||||
|
||||
private:
|
||||
PyObject* m_ptr;
|
||||
@@ -387,7 +404,7 @@ namespace api
|
||||
static PyObject*
|
||||
get(T const& x, U)
|
||||
{
|
||||
return python::incref(get_managed_object(x, tag));
|
||||
return python::incref(get_managed_object(x, boost::python::tag));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -410,6 +427,62 @@ template <class T> struct extract;
|
||||
// implementation
|
||||
//
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class call_proxy
|
||||
{
|
||||
public:
|
||||
call_proxy(object target) : m_target(target) {}
|
||||
operator object() const { return m_target;}
|
||||
|
||||
private:
|
||||
object m_target;
|
||||
};
|
||||
|
||||
class kwds_proxy : public call_proxy
|
||||
{
|
||||
public:
|
||||
kwds_proxy(object o = object()) : call_proxy(o) {}
|
||||
};
|
||||
class args_proxy : public call_proxy
|
||||
{
|
||||
public:
|
||||
args_proxy(object o) : call_proxy(o) {}
|
||||
kwds_proxy operator* () const { return kwds_proxy(*this);}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
detail::args_proxy api::object_operators<U>::operator* () const
|
||||
{
|
||||
object_cref2 x = *static_cast<U const*>(this);
|
||||
return boost::python::detail::args_proxy(x);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
object api::object_operators<U>::operator()(detail::args_proxy const &args) const
|
||||
{
|
||||
U const& self = *static_cast<U const*>(this);
|
||||
PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
|
||||
args.operator object().ptr(),
|
||||
0);
|
||||
return object(boost::python::detail::new_reference(result));
|
||||
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
object api::object_operators<U>::operator()(detail::args_proxy const &args,
|
||||
detail::kwds_proxy const &kwds) const
|
||||
{
|
||||
U const& self = *static_cast<U const*>(this);
|
||||
PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
|
||||
args.operator object().ptr(),
|
||||
kwds.operator object().ptr());
|
||||
return object(boost::python::detail::new_reference(result));
|
||||
|
||||
}
|
||||
|
||||
inline object::object()
|
||||
: object_base(python::incref(Py_None))
|
||||
{}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Based on boost/ref.hpp, thus:
|
||||
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
|
||||
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
|
||||
// Copyright (C) 2001 Peter Dimov
|
||||
|
||||
# if _MSC_VER+0 >= 1020
|
||||
|
||||
@@ -113,7 +113,10 @@ struct most_derived
|
||||
|
||||
# endif // SIGNATURE_JDG20020813_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)
|
||||
// For gcc 4.4 compatability, we must include the
|
||||
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
|
||||
#else // BOOST_PP_IS_ITERATING
|
||||
#if BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
@@ -176,4 +179,5 @@ get_signature(
|
||||
# undef Q
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_ITERATION_DEPTH()
|
||||
#endif // !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
# include <boost/operators.hpp>
|
||||
# include <typeinfo>
|
||||
# include <cstring>
|
||||
# include <ostream>
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
|
||||
@@ -68,8 +68,9 @@ struct with_custodian_and_ward : BasePolicy_
|
||||
|
||||
bool result = BasePolicy_::precall(args_);
|
||||
|
||||
if (!result)
|
||||
if (!result) {
|
||||
Py_DECREF(life_support);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
3
module.cmake
Normal file
3
module.cmake
Normal file
@@ -0,0 +1,3 @@
|
||||
boost_module(python DEPENDS graph numeric)
|
||||
|
||||
# numeric is there because of boost/cast.hpp from libs/python/src/errors.cpp:11
|
||||
64
src/CMakeLists.txt
Normal file
64
src/CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
if (PYTHON_DEBUG_LIBRARIES AND BUILD_BOOST_PYTHON)
|
||||
# We have detected that there might be Python debug libraries
|
||||
# available, but check for ourselves whether this is true by trying
|
||||
# to compile/link a program against them.
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "-DBOOST_DEBUG_PYTHON -DPy_DEBUG")
|
||||
get_directory_property(CMAKE_REQUIRED_INCLUDES INCLUDE_DIRECTORIES)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${PYTHON_DEBUG_LIBRARIES})
|
||||
set(CHECK_PYDEBUG_SOURCE
|
||||
"#include <boost/python/object.hpp>")
|
||||
check_cxx_source_compiles(
|
||||
"#include <boost/python/object.hpp>
|
||||
void check(PyObject *obj) { Py_INCREF(obj); } int main() { }"
|
||||
PYDEBUG_CAN_BUILD)
|
||||
|
||||
# Setup an option to enable/disable building variants with Python
|
||||
# debugging. If we were able to link against the debug libraries,
|
||||
# default to ON; otherwise, default to OFF.
|
||||
option(BUILD_PYTHON_DEBUG
|
||||
"Build an additional Boost.Python library with Python debugging enabled"
|
||||
${PYDEBUG_CAN_BUILD})
|
||||
endif (PYTHON_DEBUG_LIBRARIES AND BUILD_BOOST_PYTHON)
|
||||
|
||||
# Always build the non-debug variants of the boost_python library
|
||||
set(BUILD_PYTHON_NODEBUG ON)
|
||||
|
||||
boost_add_library(boost_python
|
||||
numeric.cpp
|
||||
list.cpp
|
||||
long.cpp
|
||||
dict.cpp
|
||||
tuple.cpp
|
||||
str.cpp
|
||||
slice.cpp
|
||||
converter/from_python.cpp
|
||||
converter/registry.cpp
|
||||
converter/type_id.cpp
|
||||
object/enum.cpp
|
||||
object/class.cpp
|
||||
object/function.cpp
|
||||
object/inheritance.cpp
|
||||
object/life_support.cpp
|
||||
object/pickle_support.cpp
|
||||
errors.cpp
|
||||
module.cpp
|
||||
converter/builtin_converters.cpp
|
||||
converter/arg_to_python_base.cpp
|
||||
object/iterator.cpp
|
||||
object/stl_iterator.cpp
|
||||
object_protocol.cpp
|
||||
object_operators.cpp
|
||||
wrapper.cpp
|
||||
import.cpp
|
||||
exec.cpp
|
||||
object/function_doc_signature.cpp
|
||||
|
||||
STATIC_COMPILE_FLAGS "-DBOOST_PYTHON_SOURCE -DBOOST_PYTHON_STATIC_LIB"
|
||||
SHARED_COMPILE_FLAGS "-DBOOST_PYTHON_SOURCE"
|
||||
PYTHON_NODEBUG_LINK_LIBS "${PYTHON_LIBRARIES}"
|
||||
|
||||
# Support for Python debugging
|
||||
EXTRA_VARIANTS PYTHON_NODEBUG:PYTHON_DEBUG
|
||||
PYTHON_DEBUG_COMPILE_FLAGS "-DBOOST_DEBUG_PYTHON -DPy_DEBUG"
|
||||
PYTHON_DEBUG_LINK_LIBS "${PYTHON_DEBUG_LIBRARIES}"
|
||||
)
|
||||
194
test/CMakeLists.txt
Normal file
194
test/CMakeLists.txt
Normal file
@@ -0,0 +1,194 @@
|
||||
macro(bpl_test TESTNAME)
|
||||
parse_arguments(BPL_TEST
|
||||
"ARGS"
|
||||
""
|
||||
${ARGN})
|
||||
|
||||
# Determine the Python and C++ source files for this test
|
||||
if (BPL_TEST_DEFAULT_ARGS)
|
||||
# First argument is the Python source we will run, the rest are
|
||||
# either extra Python sources we're dependent on or C++ files from
|
||||
# which we will build extension modules.
|
||||
car(BPL_TEST_PYSOURCE ${BPL_TEST_DEFAULT_ARGS})
|
||||
cdr(BPL_TEST_DEFAULT_ARGS ${BPL_TEST_DEFAULT_ARGS})
|
||||
|
||||
get_filename_component(BPL_TEST_PYBASE ${BPL_TEST_PYSOURCE} NAME_WE)
|
||||
foreach(SRC ${BPL_TEST_DEFAULT_ARGS})
|
||||
get_filename_component(BPL_SRC_EXT ${SRC} EXT)
|
||||
if (BPL_SRC_EXT STREQUAL ".cpp")
|
||||
# Build a Python extension module from this source file
|
||||
get_filename_component(BPL_SRC_NAME ${SRC} NAME_WE)
|
||||
if(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
|
||||
boost_python_extension(${BPL_SRC_NAME}_ext ${SRC})
|
||||
else(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
|
||||
boost_python_extension(${BPL_SRC_NAME} ${SRC})
|
||||
endif(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
|
||||
endif (BPL_SRC_EXT STREQUAL ".cpp")
|
||||
endforeach(SRC ${BPL_TEST_DEFAULT_ARGS})
|
||||
else (BPL_TEST_DEFAULT_ARGS)
|
||||
set(BPL_TEST_PYSOURCE "${TESTNAME}.py")
|
||||
|
||||
# Build a Python extension module from this source file
|
||||
boost_python_extension(${TESTNAME}_ext "${TESTNAME}.cpp")
|
||||
endif(BPL_TEST_DEFAULT_ARGS)
|
||||
|
||||
# We'll need the full patch to run the Python test
|
||||
set(BPL_TEST_PYSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${BPL_TEST_PYSOURCE})
|
||||
|
||||
# Run the test itself
|
||||
file(TO_NATIVE_PATH "${LIBRARY_OUTPUT_PATH}" PYTHONPATH)
|
||||
if(WIN32 AND NOT UNIX)
|
||||
string(REPLACE "\\" "\\\\" PYTHONPATH "${PYTHONPATH}")
|
||||
endif(WIN32 AND NOT UNIX)
|
||||
add_test("${PROJECT_NAME}::${TESTNAME}"
|
||||
${PYTHON_EXECUTABLE}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/pyrun.py"
|
||||
"${PYTHONPATH}"
|
||||
${BPL_TEST_PYSOURCE} ${BPL_TEST_ARGS})
|
||||
endmacro(bpl_test)
|
||||
|
||||
macro(py_run TESTNAME)
|
||||
boost_test_run(${TESTNAME}
|
||||
${TESTNAME}.cpp
|
||||
DEPENDS boost_python STATIC
|
||||
LINK_LIBS ${PYTHON_LIBRARIES})
|
||||
endmacro(py_run)
|
||||
|
||||
boost_test_run(exec
|
||||
DEPENDS boost_python STATIC
|
||||
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/exec.py"
|
||||
LINK_LIBS ${PYTHON_LIBRARIES})
|
||||
boost_test_run(exec-dynamic
|
||||
exec.cpp
|
||||
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/exec.py"
|
||||
DEPENDS boost_python SHARED
|
||||
LINK_LIBS ${PYTHON_LIBRARIES})
|
||||
|
||||
bpl_test(crossmod_exception
|
||||
crossmod_exception.py crossmod_exception_a.cpp crossmod_exception_b.cpp)
|
||||
|
||||
bpl_test(injected)
|
||||
bpl_test(properties)
|
||||
bpl_test(return_arg)
|
||||
bpl_test(staticmethod)
|
||||
bpl_test(shared_ptr)
|
||||
bpl_test(andreas_beyer)
|
||||
bpl_test(polymorphism)
|
||||
bpl_test(polymorphism2)
|
||||
|
||||
bpl_test(wrapper_held_type)
|
||||
bpl_test(polymorphism2_auto_ptr)
|
||||
|
||||
bpl_test(auto_ptr)
|
||||
|
||||
bpl_test(minimal)
|
||||
bpl_test(args)
|
||||
bpl_test(raw_ctor)
|
||||
bpl_test(numpy numpy.py printer.py numeric_tests.py numarray_tests.py numpy.cpp)
|
||||
bpl_test(enum)
|
||||
bpl_test(exception_translator)
|
||||
bpl_test(pearu1 test_cltree.py cltree.cpp)
|
||||
bpl_test(try newtest.py m1.cpp m2.cpp)
|
||||
bpl_test(const_argument)
|
||||
bpl_test(keywords keywords_test.py keywords.cpp)
|
||||
|
||||
boost_python_extension(builtin_converters_ext test_builtin_converters.cpp)
|
||||
bpl_test(builtin_converters test_builtin_converters.py builtin_converters_ext)
|
||||
|
||||
bpl_test(test_pointer_adoption)
|
||||
bpl_test(operators)
|
||||
bpl_test(callbacks)
|
||||
bpl_test(defaults)
|
||||
|
||||
bpl_test(object)
|
||||
bpl_test(list)
|
||||
bpl_test(long)
|
||||
bpl_test(dict)
|
||||
bpl_test(tuple)
|
||||
bpl_test(str)
|
||||
bpl_test(slice)
|
||||
|
||||
bpl_test(virtual_functions)
|
||||
bpl_test(back_reference)
|
||||
bpl_test(implicit)
|
||||
bpl_test(data_members)
|
||||
|
||||
bpl_test(ben_scott1)
|
||||
|
||||
bpl_test(bienstman1)
|
||||
bpl_test(bienstman2)
|
||||
bpl_test(bienstman3)
|
||||
|
||||
bpl_test(multi_arg_constructor)
|
||||
# TODO: A bug in the Win32 intel compilers causes compilation of one
|
||||
# of our tests to take forever when debug symbols are
|
||||
# enabled. This rule turns them off when added to the requirements
|
||||
# section
|
||||
# <toolset>intel-win:<debug-symbols>off
|
||||
|
||||
bpl_test(iterator iterator.py iterator.cpp input_iterator.cpp)
|
||||
|
||||
bpl_test(stl_iterator stl_iterator.py stl_iterator.cpp)
|
||||
|
||||
bpl_test(extract)
|
||||
|
||||
bpl_test (crossmod_opaque
|
||||
crossmod_opaque.py crossmod_opaque_a.cpp crossmod_opaque_b.cpp)
|
||||
|
||||
bpl_test(opaque)
|
||||
bpl_test(voidptr)
|
||||
|
||||
bpl_test(pickle1)
|
||||
bpl_test(pickle2)
|
||||
bpl_test(pickle3)
|
||||
bpl_test(pickle4)
|
||||
|
||||
bpl_test(nested)
|
||||
|
||||
bpl_test(docstring)
|
||||
|
||||
bpl_test(vector_indexing_suite)
|
||||
|
||||
bpl_test(pointer_vector)
|
||||
# TODO: Turn off this test on HP CXX, as the test hangs when executing.
|
||||
# Whenever the cause for the failure of the polymorphism test is found
|
||||
# and fixed, this should be retested.
|
||||
# <toolset>hp_cxx:<build>no
|
||||
|
||||
boost_python_extension(map_indexing_suite_ext
|
||||
map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp)
|
||||
|
||||
bpl_test(map_indexing_suite
|
||||
map_indexing_suite.py map_indexing_suite_ext)
|
||||
|
||||
|
||||
# --- unit tests of library components ---
|
||||
|
||||
boost_test_compile(indirect_traits_test)
|
||||
boost_test_run(destroy_test)
|
||||
py_run(pointer_type_id_test)
|
||||
py_run(bases)
|
||||
boost_test_run(if_else)
|
||||
py_run(pointee)
|
||||
boost_test_run(result)
|
||||
|
||||
boost_test_compile(string_literal)
|
||||
boost_test_compile(borrowed)
|
||||
boost_test_compile(object_manager)
|
||||
boost_test_compile(copy_ctor_mutates_rhs)
|
||||
|
||||
py_run(upcast)
|
||||
|
||||
boost_test_compile(select_holder)
|
||||
|
||||
boost_test_run(select_from_python_test
|
||||
select_from_python_test.cpp ../src/converter/type_id.cpp
|
||||
COMPILE_FLAGS "-DBOOST_PYTHON_STATIC_LIB"
|
||||
LINK_LIBS ${PYTHON_LIBRARIES})
|
||||
|
||||
boost_test_compile(select_arg_to_python_test)
|
||||
|
||||
boost_test_compile_fail(raw_pyobject_fail1)
|
||||
boost_test_compile_fail(raw_pyobject_fail2)
|
||||
boost_test_compile_fail(as_to_python_function)
|
||||
boost_test_compile_fail(object_fail1)
|
||||
@@ -13,6 +13,7 @@
|
||||
# endif
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# include <eh.h> // for _set_se_translator()
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4297)
|
||||
# pragma warning(disable:4535)
|
||||
|
||||
@@ -38,26 +38,61 @@ object obj_getattr(object x, char const* name)
|
||||
return x.attr(name);
|
||||
}
|
||||
|
||||
object obj_objgetattr(object x, object const& name)
|
||||
{
|
||||
return x.attr(name);
|
||||
}
|
||||
|
||||
object obj_const_getattr(object const& x, char const* name)
|
||||
{
|
||||
return x.attr(name);
|
||||
}
|
||||
|
||||
object obj_const_objgetattr(object const& x, object const& name)
|
||||
{
|
||||
return x.attr(name);
|
||||
}
|
||||
|
||||
void obj_setattr(object x, char const* name, object value)
|
||||
{
|
||||
x.attr(name) = value;
|
||||
}
|
||||
|
||||
void obj_objsetattr(object x, object const& name, object value)
|
||||
{
|
||||
x.attr(name) = value;
|
||||
}
|
||||
|
||||
void obj_setattr42(object x, char const* name)
|
||||
{
|
||||
x.attr(name) = 42;
|
||||
}
|
||||
|
||||
void obj_objsetattr42(object x, object const& name)
|
||||
{
|
||||
x.attr(name) = 42;
|
||||
}
|
||||
|
||||
void obj_moveattr(object& x, char const* src, char const* dst)
|
||||
{
|
||||
x.attr(dst) = x.attr(src);
|
||||
}
|
||||
|
||||
void obj_objmoveattr(object& x, object const& src, object const& dst)
|
||||
{
|
||||
x.attr(dst) = x.attr(src);
|
||||
}
|
||||
|
||||
void obj_delattr(object x, char const* name)
|
||||
{
|
||||
x.attr(name).del();
|
||||
}
|
||||
|
||||
void obj_objdelattr(object x, object const& name)
|
||||
{
|
||||
x.attr(name).del();
|
||||
}
|
||||
|
||||
object obj_getitem(object x, object key)
|
||||
{
|
||||
return x[key];
|
||||
@@ -108,11 +143,21 @@ bool test_attr(object y, char* name)
|
||||
return y.attr(name);
|
||||
}
|
||||
|
||||
bool test_objattr(object y, object& name)
|
||||
{
|
||||
return y.attr(name);
|
||||
}
|
||||
|
||||
bool test_not_attr(object y, char* name)
|
||||
{
|
||||
return !y.attr(name);
|
||||
}
|
||||
|
||||
bool test_not_objattr(object y, object& name)
|
||||
{
|
||||
return !y.attr(name);
|
||||
}
|
||||
|
||||
bool test_item(object y, object key)
|
||||
{
|
||||
return y[key];
|
||||
@@ -142,6 +187,11 @@ bool check_string_slice()
|
||||
return s.slice(2,-1).slice(1,-1) == "lo, wor";
|
||||
}
|
||||
|
||||
object test_call(object c, object args, object kwds)
|
||||
{
|
||||
return c(*args, **kwds);
|
||||
}
|
||||
|
||||
bool check_binary_operators()
|
||||
{
|
||||
int y;
|
||||
@@ -301,11 +351,17 @@ BOOST_PYTHON_MODULE(object_ext)
|
||||
def("number", number);
|
||||
|
||||
def("obj_getattr", obj_getattr);
|
||||
def("obj_objgetattr", obj_objgetattr);
|
||||
def("obj_const_getattr", obj_const_getattr);
|
||||
def("obj_const_objgetattr", obj_const_objgetattr);
|
||||
def("obj_setattr", obj_setattr);
|
||||
def("obj_objsetattr", obj_objsetattr);
|
||||
def("obj_setattr42", obj_setattr42);
|
||||
def("obj_objsetattr42", obj_objsetattr42);
|
||||
def("obj_moveattr", obj_moveattr);
|
||||
|
||||
def("obj_objmoveattr", obj_objmoveattr);
|
||||
def("obj_delattr", obj_delattr);
|
||||
def("obj_objdelattr", obj_objdelattr);
|
||||
|
||||
def("obj_getitem", obj_getitem);
|
||||
def("obj_getitem3", obj_getitem);
|
||||
@@ -319,11 +375,14 @@ BOOST_PYTHON_MODULE(object_ext)
|
||||
def("test_not", test_not);
|
||||
|
||||
def("test_attr", test_attr);
|
||||
def("test_objattr", test_objattr);
|
||||
def("test_not_attr", test_not_attr);
|
||||
def("test_not_objattr", test_not_objattr);
|
||||
|
||||
def("test_item", test_item);
|
||||
def("test_not_item", test_not_item);
|
||||
|
||||
def("test_call", test_call);
|
||||
def("check_binary_operators", check_binary_operators);
|
||||
def("check_inplace", check_inplace);
|
||||
def("check_string_slice", check_string_slice);
|
||||
|
||||
@@ -34,29 +34,68 @@
|
||||
>>> try: obj_getattr(x, 'foo')
|
||||
... except AttributeError: pass
|
||||
... else: print 'expected an exception'
|
||||
>>> try: obj_objgetattr(x, 'objfoo')
|
||||
... except AttributeError: pass
|
||||
... else: print 'expected an exception'
|
||||
|
||||
>>> obj_setattr(x, 'foo', 1)
|
||||
>>> x.foo
|
||||
1
|
||||
>>> obj_objsetattr(x, 'objfoo', 1)
|
||||
>>> try:obj_objsetattr(x, 1)
|
||||
... except TypeError: pass
|
||||
... else: print 'expected an exception'
|
||||
>>> x.objfoo
|
||||
1
|
||||
>>> obj_getattr(x, 'foo')
|
||||
1
|
||||
>>> obj_objgetattr(x, 'objfoo')
|
||||
1
|
||||
>>> try:obj_objgetattr(x, 1)
|
||||
... except TypeError: pass
|
||||
... else: print 'expected an exception'
|
||||
>>> obj_const_getattr(x, 'foo')
|
||||
1
|
||||
>>> obj_const_objgetattr(x, 'objfoo')
|
||||
1
|
||||
>>> obj_setattr42(x, 'foo')
|
||||
>>> x.foo
|
||||
42
|
||||
>>> obj_objsetattr42(x, 'objfoo')
|
||||
>>> x.objfoo
|
||||
42
|
||||
>>> obj_moveattr(x, 'foo', 'bar')
|
||||
>>> x.bar
|
||||
42
|
||||
>>> obj_objmoveattr(x, 'objfoo', 'objbar')
|
||||
>>> x.objbar
|
||||
42
|
||||
>>> test_attr(x, 'foo')
|
||||
1
|
||||
>>> test_objattr(x, 'objfoo')
|
||||
1
|
||||
>>> test_not_attr(x, 'foo')
|
||||
0
|
||||
>>> test_not_objattr(x, 'objfoo')
|
||||
0
|
||||
>>> x.foo = None
|
||||
>>> test_attr(x, 'foo')
|
||||
0
|
||||
>>> x.objfoo = None
|
||||
>>> test_objattr(x, 'objfoo')
|
||||
0
|
||||
>>> test_not_attr(x, 'foo')
|
||||
1
|
||||
>>> test_not_objattr(x, 'objfoo')
|
||||
1
|
||||
>>> obj_delattr(x, 'foo')
|
||||
>>> obj_objdelattr(x, 'objfoo')
|
||||
>>> try:obj_delattr(x, 'foo')
|
||||
... except AttributeError: pass
|
||||
... else: print 'expected an exception'
|
||||
>>> try:obj_objdelattr(x, 'objfoo')
|
||||
... except AttributeError: pass
|
||||
... else: print 'expected an exception'
|
||||
|
||||
Items
|
||||
|
||||
@@ -95,7 +134,12 @@
|
||||
|
||||
Operators
|
||||
|
||||
|
||||
>>> def print_args(*args, **kwds):
|
||||
... print args, kwds
|
||||
>>> test_call(print_args, (0, 1, 2, 3), {'a':'A'})
|
||||
(0, 1, 2, 3) {'a': 'A'}
|
||||
|
||||
|
||||
>>> assert check_binary_operators()
|
||||
|
||||
>>> class X: pass
|
||||
|
||||
Reference in New Issue
Block a user