2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-20 04:42:28 +00:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Dave Abrahams
480aaf6400 gcc-3.0.x needs to use typeid(x).name() instead of type_info directly for cross-shared-lib RTTI.
[SVN r12126]
2001-12-19 22:23:39 +00:00
Dave Abrahams
26b15fe373 initial checkin
[SVN r12123]
2001-12-19 16:06:31 +00:00
Dave Abrahams
eadcc79089 workaround for missing 'C' standard headers
[SVN r12104]
2001-12-18 14:10:06 +00:00
Dave Abrahams
35fd3dfaa1 Integrated Scott Snyder's nested class patch
[SVN r12080]
2001-12-17 05:49:24 +00:00
Dave Abrahams
3505ac2516 initial checkin
[SVN r12077]
2001-12-16 18:38:05 +00:00
Dave Abrahams
946ed17ae1 initial checkin
[SVN r12075]
2001-12-16 18:18:58 +00:00
Dave Abrahams
a4747eb10a *** empty log message ***
[SVN r12074]
2001-12-16 18:09:42 +00:00
nobody
4d6772dac2 This commit was manufactured by cvs2svn to create branch 'newbpl'.
[SVN r8341]
2000-11-27 08:04:06 +00:00
50 changed files with 5399 additions and 180 deletions

57
Jamfile Normal file
View File

@@ -0,0 +1,57 @@
subproject libs/python ;
# bring in the rules for python
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
include <module@>python.jam ;
PYTHON_PROPERTIES
+= <metrowerks><*><cxxflags>"-inline deferred"
<cxx><*><include>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers
;
local export-bpl ;
if $(NT)
{
# Stick this in the property set to deal with gcc
export-bpl = export-bpl-logic ;
rule export-bpl-logic ( toolset variant : properties * )
{
if $(toolset) != gcc
{
properties += <define>BOOST_PYTHON_EXPORT=__declspec(dllexport) ;
}
else
{
properties += <define>BOOST_PYTHON_EXPORT= ;
}
return $(properties) ;
}
}
dll bpl
:
src/converter/body.cpp
src/converter/handle.cpp
src/converter/registry.cpp
src/converter/wrapper.cpp
src/converter/unwrap.cpp
src/converter/unwrapper.cpp
src/converter/type_id.cpp
src/object/class.cpp
src/object/function.cpp
:
$(PYTHON_PROPERTIES)
$(export-bpl)
# <define>BOOST_PYTHON_TRACE
;
extension m1 : test/m1.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
: <gcc><*><define>BOOST_PYTHON_EXPORT=
: debug-python ;
extension m2 : test/m2.cpp <lib>bpl # <define>BOOST_PYTHON_TRACE
: <gcc><*><define>BOOST_PYTHON_EXPORT=
: debug-python ;
boost-python-runtest try : test/newtest.py <lib>m1 <lib>m2 : : debug-python ;

308
doc/new-conversions.html Normal file
View File

@@ -0,0 +1,308 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>A New Type Conversion Mechanism for Boost.Python</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p><img border="0" src="../../../c++boost.gif" width="277" height="86"
alt="boost logo"></p>
<h1>A New Type Conversion Mechanism for Boost.Python</h1>
<p>By <a href="../../../people/dave_abrahams.htm">David Abrahams</a>.
<h2>Introduction</h2>
This document describes a redesign of the mechanism for automatically
converting objects between C++ and Python. The current implementation
uses two functions for any type <tt>T</tt>:
<blockquote><pre>
U from_python(PyObject*, type&lt;T&gt;);
void to_python(V);
</pre></blockquote>
where U is convertible to T and T is convertible to V. These functions
are at the heart of C++/Python interoperability in Boost.Python, so
why would we want to change them? There are many reasons:
<h3>Bugs</h3>
<p>Firstly, the current mechanism relies on a common C++ compiler
bug. This is not just embarrassing: as compilers get to be more
conformant, the library stops working. The issue, in detail, is the
use of inline friend functions in templates to generate
conversions. It is a very powerful, and legal technique as long as
it's used correctly:
<blockquote><pre>
template &lt;class Derived&gt;
struct add_some_functions
{
friend <i>return-type</i> some_function1(..., Derived <i>cv-*-&amp;-opt</i>, ...);
friend <i>return-type</i> some_function2(..., Derived <i>cv-*-&amp;-opt</i>, ...);
};
template &lt;class T&gt;
struct some_template : add_some_functions&lt;some_template&lt;T&gt; &gt;
{
};
</pre></blockquote>
The <tt>add_some_functions</tt> template generates free functions
which operate on <tt>Derived</tt>, or on related types. Strictly
speaking the related types are not just cv-qualified <tt>Derived</tt>
values, pointers and/or references. Section 3.4.2 in the standard
describes exactly which types you must use as parameters to these
functions if you want the functions to be found
(there is also a less-technical description in section 11.5.1 of
C++PL3 <a href="#ref_1">[1]</a>). Suffice it to say that
with the current design, the <tt>from_python</tt> and
<tt>to_python</tt> functions are not supposed to be callable under any
conditions!
<h3>Compilation and Linking Time</h3>
The conversion functions generated for each wrapped class using the
above technique are not function templates, but regular functions. The
upshot is that they must <i>all</i> be generated regardless of whether
they are actually used. Generating all of those functions can slow
down module compilation, and resolving the references can slow down
linking.
<h3>Efficiency</h3>
The conversion functions are primarily used in (member) function
wrappers to convert the arguments and return values. Being functions,
converters have no interface which allows us to ask &quot;will the
conversion succeed?&quot; without calling the function. Since the
return value of the function must be the object to be passed as an
argument, Boost.Python currently uses C++ exception-handling to detect
an unsuccessful conversion. It's not a particularly good use of
exception-handling, since the failure is not handled very far from
where it occurred. More importantly, it means that C++ exceptions are
thrown during overload resolution as we seek an overload that matches
the arguments passed. Depending on the implementation, this approach
can result in significant slowdowns.
<p>It is also unclear that the current library generates a minimal
amount of code for any type conversion. Many of the conversion
functions are nontrivial, and partly because of compiler limitations,
they are declared <tt>inline</tt>. Also, we could have done a better
job separating the type-specific conversion code from the code which
is type-independent.
<h3>Cross-module Support</h3>
The current strategy requires every module to contain the definition
of conversions it uses. In general, a new module can never supply
conversion code which is used by another module. Ralf Grosse-Kunstleve
designed a clever system which imports conversions directly from one
library into another using some explicit declarations, but it has some
disadvantages also:
<ol>
<li>The system Ullrich Koethe designed for implicit conversion between
wrapped classes related through inheritance does not currently work if
the classes are defined in separate modules.
<li>The writer of the importing module is required to know the name of
the module supplying the imported conversions.
<li>There can be only one way to extract any given C++ type from a
Python object in a given module.
</ol>
The first item might be addressed by moving Boost.Python into a shared
library, but the other two cannot. Ralf turned the limitation in item
two into a feature: the required module is loaded implicitly when a
conversion it defines is invoked. We will probably want to provide
that functionality anyway, but it's not clear that we should require
the declaration of all such conversions. The final item is a more
serious limitation. If, for example, new numeric types are defined in
separate modules, and these types can all be converted to
<tt>double</tt>s, we have to choose just one conversion method.
<h3>Ease-of-use</h3>
One persistent source of confusion for users of Boost.Python has been
the fact that conversions for a class are not be visible at
compile-time until the declaration of that class has been seen. When
the user tries to expose a (member) function operating on or returning
an instance of the class in question, compilation fails...even though
the user goes on to expose the class in the same translation unit!
<p>
The new system lifts all compile-time checks for the existence of
particular type conversions and replaces them with runtime checks, in
true Pythonic style. While this might seem cavalier, the compile-time
checks are actually not much use in the current system if many classes
are wrapped in separate modules, since the checks are based only on
the user's declaration that the conversions exist.
<h2>The New Design</h2>
<h3>Motivation</h3>
The new design was heavily influenced by a desire to generate as
little code as possible in extension modules. Some of Boost.Python's
clients are enormous projects where link time is proportional to the
amount of object code, and there are many Python extension modules. As
such, we try to keep type-specific conversion code out of modules
other than the one the converters are defined in, and rely as much as
possible on centralized control through a shared library.
<h3>The Basics</h3>
The library contains a <tt>registry</tt> which maps runtime type
identifiers (actually an extension of <tt>std::type_info</tt> which
preserves references and constness) to entries containing type
converters. An <tt>entry</tt> can contain only one converter from C++ to Python
(<tt>wrapper</tt>), but many converters from Python to C++
(<tt>unwrapper</tt>s). <font color="#ff0000">What should happen if
multiple modules try to register wrappers for the same type?</font>. Wrappers
and unwrappers are known as <tt>body</tt> objects, and are accessed
by the user and the library (in its function-wrapping code) through
corresponding <tt>handle</tt> (<tt>wrap&lt;T&gt;</tt> and
<tt>unwrap&lt;T&gt;</tt>) objects. The <tt>handle</tt> objects are
extremely lightweight, and delegate <i>all</i> of their operations to
the corresponding <tt>body</tt>.
<p>
When a <tt>handle</tt> object is constructed, it accesses the
registry to find a corresponding <tt>body</tt> that can convert the
handle's constructor argument. Actually the registry record for any
type
<tt>T</tt>used in a module is looked up only once and stored in a
static <tt>registration&lt;T&gt;</tt> object for efficiency. For
example, if the handle is an <tt>unwrap&lt;Foo&amp;&gt;</tt> object,
the <tt>entry</tt> for <tt>Foo&amp;</tt> is looked up in the
<tt>registry</tt>, and each <tt>unwrapper</tt> it contains is queried
to determine if it can convert the
<tt>PyObject*</tt> with which the <tt>unwrap</tt> was constructed. If
a body object which can perform the conversion is found, a pointer to
it is stored in the handle. A body object may at any point store
additional data in the handle to speed up the conversion process.
<p>
Now that the handle has been constructed, the user can ask it whether
the conversion can be performed. All handles can be tested as though
they were convertible to <tt>bool</tt>; a <tt>true</tt> value
indicates success. If the user forges ahead and tries to do the
conversion without checking when no conversion is possible, an
exception will be thrown as usual. The conversion itself is performed
by the body object.
<h3>Handling complex conversions</h3>
<p>Some conversions may require a dynamic allocation. For example,
when a Python tuple is converted to a <tt>std::vector&lt;double&gt;
const&amp;</tt>, we need some storage into which to construct the
vector so that a reference to it can be formed. Furthermore, multiple
conversions of the same type may need to be &quot;active&quot;
simultaneously, so we can't keep a single copy of the storage
anywhere. We could keep the storage in the <tt>body</tt> object, and
have the body clone itself in case the storage is used, but in that
case the storage in the body which lives in the registry is never
used. If the storage was actually an object of the target type (the
safest way in C++), we'd have to find a way to construct one for the
body in the registry, since it may not have a default constructor.
<p>
The most obvious way out of this quagmire is to allocate the object using a
<i>new-expression</i>, and store a pointer to it in the handle. Since
the <tt>body</tt> object knows everything about the data it needs to
allocate (if any), it is also given responsibility for destroying that
data. When the <tt>handle</tt> is destroyed it asks the <tt>body</tt>
object to tear down any data it may have stored there. In many ways,
you can think of the <tt>body</tt> as a &quot;dynamically-determined
vtable&quot; for the handle.
<h3>Eliminating Redundancy</h3>
If you look at the current Boost.Python code, you'll see that there
are an enormous number of conversion functions generated for each
wrapped class. For a given class <tt>T</tt>, functions are generated
to extract the following types <tt>from_python</tt>:
<blockquote><pre>
T*
T const*
T const* const&amp;
T* const&amp;
T&amp;
T const&amp;
T
std::auto_ptr&lt;T&gt;&amp;
std::auto_ptr&lt;T&gt;
std::auto_ptr&lt;T&gt; const&amp;
boost::shared_ptr&lt;T&gt;&amp;
boost::shared_ptr&lt;T&gt;
boost::shared_ptr&lt;T&gt; const&amp;
</pre></blockquote>
Most of these are implemented in terms of just a few conversions, and
<t>if you're lucky</t>, they will be inlined and cause no extra
overhead. In the new system, however, a significant amount of data
will be associated with each type that needs to be converted. We
certainly don't want to register a separate unwrapper object for all
of the above types.
<p>Fortunately, much of the redundancy can be eliminated. For example,
if we generate an unwrapper for <tt>T&</tt>, we don't need an
unwrapper for <tt>T const&</tt> or <tt>T</tt>. Accordingly, the user's
request to wrap/unwrap a given type is translated at compile-time into
a request which helps to eliminate redundancy. The rules used to
<tt>unwrap</tt> a type are:
<ol>
<li> Treat built-in types specially: when unwrapping a value or
constant reference to one of these, use a value for the target
type. It will bind to a const reference if neccessary, and more
importantly, avoids having to dynamically allocate room for
an lvalue of types which can be cheaply copied.
<li>
Reduce everything else to a reference to an un-cv-qualified type
where possible. Since cv-qualification is lost on Python
anyway, there's no point in trying to convert to a
<tt>const&amp;</tt>. <font color="#ff0000">What about conversions
to values like the tuple-&gt;vector example above? It seems to me
that we don't want to make a <tt>vector&lt;double&gt;&amp;</tt>
(non-const) converter available for that case. We may need to
rethink this slightly.</font>
</ol>
<h3>Efficient Argument Conversion</h3>
Since type conversions are primarily used in function wrappers, an
optimization is provided for the case where a group of conversions are
used together. Each <tt>handle</tt> class has a corresponding
&quot;<tt>_more</tt>&quot; class which does the same job, but has a
trivial destructor. Instead of asking each &quot;<tt>_more</tt>&quot;
handle to destroy its own body, it is linked into an endogenous list
managed by the first (ordinary) handle. The <tt>wrap</tt> and
<tt>unwrap</tt> destructors are responsible for traversing that list
and asking each <tt>body</tt> class to tear down its
<tt>handle</tt>. This mechanism is also used to determine if all of
the argument/return-value conversions can succeed with a single
function call in the function wrapping code. <font color="#ff0000">We
might need to handle return values in a separate step for Python
callbacks, since the availablility of a conversion won't be known
until the result object is retrieved.</font>
<br>
<hr>
<h2>References</h2>
<p><a name="ref_1">[1]</a>B. Stroustrup, The C++ Programming Language
Special Edition Addison-Wesley, ISBN 0-201-70073-5.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->19 December 2001<!--webbot bot="Timestamp" endspan i-checksum="31283" --></p>
<p>© Copyright David Abrahams, 2001</p>
</body>
</html>

111
doc/new-conversions.txt Normal file
View File

@@ -0,0 +1,111 @@
This hierarchy contains converter handle classes.
+-------------+
| noncopyable |
+-------------+
^
| A common base class used so that
+--------+--------+ conversions can be linked into a
| conversion_base | chain for efficient argument
+-----------------+ conversion
^
|
+---------+-----------+
| |
+-----------+----+ +------+-------+ only used for
| unwrap_more<T> | | wrap_more<T> | chaining, and don't manage any
+----------------+ +--------------+ resources.
^ ^
| |
+-----+-----+ +-------+-+ These converters are what users
| unwrap<T> | | wrap<T> | actually touch, but they do so
+-----------+ +---------+ through a type generator which
minimizes the number of converters
that must be generated, so they
Each unwrap<T>, unwrap_more<T>, wrap<T>, wrap_more<T> converter holds
a reference to an appropriate converter object
This hierarchy contains converter body classes
Exposes use/release which
are needed in case the converter
+-----------+ in the registry needs to be
| converter | cloned. That occurs when a
+-----------+ unwrap target type is not
^ contained within the Python object.
|
+------------------+-----+
| |
+--------+-------+ Exposes |
| unwrapper_base | convertible() |
+----------------+ |
^ |
| |
+--------+----+ +-----+-----+
| unwrapper<T>| | wrapper<T>|
+-------------+ +-----------+
Exposes T convert(PyObject*) Exposes PyObject* convert(T)
unwrap:
constructed with a PyObject*, whose reference count is
incremented.
find the registry entry for the target type
look in the collection of converters for one which claims to be
able to convert the PyObject to the target type.
stick a pointer to the unwrapper in the unwrap object
when unwrap is queried for convertibility, it checks to see
if it has a pointer to an unwrapper.
on conversion, the unwrapper is asked to allocate an
implementation if the unwrap object isn't already holding
one. The unwrap object "takes ownership" of the unwrapper's
implementation. No memory allocation will actually take place
unless this is a value conversion.
on destruction, the unwrapper is asked to free any implementation
held by the unwrap object. No memory deallocation actually
takes place unless this is a value conversion
on destruction, the reference count on the held PyObject is
decremented.
We need to make sure that by default, you can't instantiate
callback<> for reference and pointer return types: although the
unwrappers may exist, they may convert by-value, which would cause
the referent to be destroyed upon return.
wrap:
find the registry entry for the source type
see if there is a converter. If found, stick a pointer to it in
the wrap object.
when queried for convertibility, it checks to see if it has a
pointer to a converter.
on conversion, a reference to the target PyObject is held by the
converter. Generally, the PyObject will have been created by the
converter, but in certain cases it may be a pre-existing object,
whose reference count will have been incremented.
when a wrap<T> x is used to return from a C++ function,
x.release() is returned so that x no longer holds a reference to
the PyObject when destroyed.
Otherwise, on destruction, any PyObject still held has its
reference-count decremented.
When a converter is created by the user, the appropriate element must
be added to the registry; when it is destroyed, it must be removed
from the registry.

View File

@@ -0,0 +1,210 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for 5-argument member functions and 6-argument free
// functions by gen_call.py
#ifndef CALL_DWA20011214_HPP
# define CALL_DWA20011214_HPP
# include <boost/python/detail/returning.hpp>
namespace boost { namespace python {
template <class R>
PyObject* call(R (*f)(), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (*f)(A0), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (*f)(A0, A1), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (*f)(A0, A1, A2), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (*f)(A0, A1, A2, A3), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (*f)(A0, A1, A2, A3, A4), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (*f)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
// Member functions
template <class R, class A0>
PyObject* call(R (A0::*f)(), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0>
PyObject* call(R (A0::*f)() const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1>
PyObject* call(R (A0::*f)(A1) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2>
PyObject* call(R (A0::*f)(A1, A2) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3>
PyObject* call(R (A0::*f)(A1, A2, A3) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4>
PyObject* call(R (A0::*f)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
PyObject* call(R (A0::*f)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
}} // namespace boost::python
#endif // CALL_DWA20011214_HPP

View File

@@ -0,0 +1,82 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONVERT_DWA20011129_HPP
# define CONVERT_DWA20011129_HPP
# include <boost/python/converter/target.hpp>
# include <boost/python/converter/source.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/unwrap.hpp>
namespace boost { namespace python {
namespace detail
{
template <class T>
struct converter_gen
{
typedef T value_type;
typedef typename converter::source<value_type>::type source;
typedef converter::wrap_<source> wrap;
typedef converter::wrap_more_<source> wrap_more;
typedef typename converter::target<value_type>::type target;
typedef converter::unwrap_<target> unwrap;
typedef converter::unwrap_more_<target> unwrap_more;
};
}
template <class T>
struct wrap : detail::converter_gen<T>::wrap
{
typedef typename detail::converter_gen<T>::wrap base;
};
template <class T>
struct wrap_more : detail::converter_gen<T>::wrap_more
{
typedef typename detail::converter_gen<T>::wrap_more base;
wrap_more(converter::handle& prev);
};
template <class T>
struct unwrap : detail::converter_gen<T>::unwrap
{
typedef typename detail::converter_gen<T>::unwrap base;
unwrap(PyObject*);
};
template <class T>
struct unwrap_more : detail::converter_gen<T>::unwrap_more
{
typedef typename detail::converter_gen<T>::unwrap_more base;
unwrap_more(PyObject*, converter::handle& prev);
};
//
// implementations
//
template <class T>
inline wrap_more<T>::wrap_more(converter::handle& prev)
: base(prev)
{
}
template <class T>
inline unwrap<T>::unwrap(PyObject* source)
: base(source)
{
}
template <class T>
inline unwrap_more<T>::unwrap_more(PyObject* source, converter::handle& prev)
: base(source, prev)
{
}
}} // namespace boost::python
#endif // CONVERT_DWA20011129_HPP

View File

@@ -0,0 +1,46 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef BODY_DWA2001127_HPP
# define BODY_DWA2001127_HPP
# include <boost/config.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT handle;
struct BOOST_PYTHON_EXPORT body
{
public:
body(type_id_t key);
virtual ~body() {}
// default implementation is a no-op
virtual void destroy_handle(handle*) const;
type_id_t key() const;
private:
type_id_t m_key;
};
//
// implementations
//
inline body::body(type_id_t key)
: m_key(key)
{
}
inline type_id_t body::key() const
{
return m_key;
}
}}} // namespace boost::python::converter
#endif // BODY_DWA2001127_HPP

View File

@@ -0,0 +1,56 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CLASS_DWA20011215_HPP
# define CLASS_DWA20011215_HPP
# include <boost/python/object/class.hpp>
# include <boost/python/converter/unwrapper.hpp>
namespace boost { namespace python { namespace converter {
struct class_unwrapper_base
{
class_unwrapper_base(type_id_t sought_type);
void*
};
template <class T>
struct class_unwrapper
{
struct ref_unwrapper : unwrapper<T&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
struct const_ref_unwrapper : unwrapper<T const&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
# endif
};
}}} // namespace boost::python::converter
#endif // CLASS_DWA20011215_HPP

View File

@@ -0,0 +1,91 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef HANDLE_DWA20011130_HPP
# define HANDLE_DWA20011130_HPP
# include <boost/python/export.hpp>
# include <boost/utility.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT body;
// The common base class for unwrap_ and wrap_ handle objects. They
// share a common base so that handles can be linked into a chain
// within a function wrapper which is managed by a single object.
struct BOOST_PYTHON_EXPORT handle : boost::noncopyable
{
public: // member functions
// All constructors take a body* passed from the derived class.
//
// Constructors taking a handle links this into a chain of
// handles, for more efficient management in function wrappers
handle(body* body);
handle(body* body, handle& prev);
// returns true iff all handles in the chain can convert their
// arguments
bool convertible() const;
// safe_bool idiom from Peter Dimov: provides handles to/from
// bool without enabling handles to integer types/void*.
private:
struct dummy { inline void nonnull() {} };
typedef void (dummy::*safe_bool)();
public:
inline operator safe_bool() const;
inline safe_bool operator!() const;
protected: // member functions for derived classes
// Get the body we hold
inline body* get_body() const;
// Release all bodies in the chain, in reverse order of
// initialization. Only actually called for the head of the chain.
void destroy();
private:
// Holds implementation
body* m_body;
// handle for next argument, if any.
handle* m_next;
};
//
// implementations
//
inline handle::handle(body* body, handle& prev)
: m_body(body), m_next(0)
{
prev.m_next = this;
}
inline handle::handle(body* body)
: m_body(body), m_next(0)
{
}
inline handle::operator handle::safe_bool() const
{
return convertible() ? &dummy::nonnull : 0;
}
inline handle::safe_bool handle::operator!() const
{
return convertible() ? 0 : &dummy::nonnull;
}
inline body* handle::get_body() const
{
return m_body;
}
}}} // namespace boost::python::converter
#endif // HANDLE_DWA20011130_HPP

View File

@@ -0,0 +1,83 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef REGISTRATION_DWA20011130_HPP
# define REGISTRATION_DWA20011130_HPP
# include <boost/config.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
struct BOOST_PYTHON_EXPORT unwrapper_base;
// This class is really sort of a "templated namespace". It manages a
// static data member which refers to the registry entry for T. This
// reference is acquired once to reduce the burden of multiple
// dictionary lookups at runtime.
template <class T>
struct registration
{
public: // member functions
// Return a converter which can convert the given Python object to
// T, or 0 if no such converter exists
static unwrapper_base* unwrapper(PyObject*);
// Return a converter which can convert T to a Python object, or 0
// if no such converter exists
static wrapper_base* wrapper();
private: // helper functions
static registry::entry* entry();
static registry::entry* find_entry();
private: // data members
static registry::entry* m_registry_entry;
};
// because this is static POD data it will be initialized to zero
template <class T>
registry::entry* registration<T>::m_registry_entry;
template <class T>
registry::entry* registration<T>::find_entry()
{
return registry::find(type_id<T>());
}
template <class T>
inline registry::entry* registration<T>::entry()
{
if (!m_registry_entry)
m_registry_entry = find_entry();
return m_registry_entry;
}
template <class T>
unwrapper_base* registration<T>::unwrapper(PyObject* p)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "retrieving unwrapper for " << type_id<T>() << std::endl;
# endif
return entry()->unwrapper(p);
}
template <class T>
wrapper_base* registration<T>::wrapper()
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "retrieving wrapper for " << type_id<T>() << std::endl;
# endif
return entry()->wrapper();
}
}}} // namespace boost::python::converter
#endif // REGISTRATION_DWA20011130_HPP

View File

@@ -0,0 +1,74 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef REGISTRY_DWA20011127_HPP
# define REGISTRY_DWA20011127_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
# include <list>
# include <memory>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
struct BOOST_PYTHON_EXPORT unwrapper_base;
// This namespace acts as a sort of singleton
namespace registry
{
// These are the elements stored in the registry
class BOOST_PYTHON_EXPORT entry
{
public: // member functions
entry();
~entry();
// Return a converter appropriate for converting the given
// Python object from_python to the C++ type with which this
// converter is associated in the registry, or 0 if no such
// converter exists.
unwrapper_base* unwrapper(PyObject*) const;
// Return a converter appropriate for converting a C++ object
// whose type this entry is associated with in the registry to a
// Python object, or 0 if no such converter exists.
wrapper_base* wrapper() const;
// Conversion classes use these functions to register
// themselves.
void insert(wrapper_base&);
void remove(wrapper_base&);
void insert(unwrapper_base&);
void remove(unwrapper_base&);
private: // types
typedef std::list<unwrapper_base*> unwrappers;
private: // helper functions
unwrappers::iterator find(unwrapper_base const&);
private: // data members
// The collection of from_python converters for the associated
// C++ type.
unwrappers m_unwrappers;
// The unique to_python converter for the associated C++ type.
converter::wrapper_base* m_wrapper;
};
BOOST_PYTHON_EXPORT entry* find(type_id_t);
BOOST_PYTHON_EXPORT void insert(wrapper_base& x);
BOOST_PYTHON_EXPORT void insert(unwrapper_base& x);
BOOST_PYTHON_EXPORT void remove(wrapper_base& x);
BOOST_PYTHON_EXPORT void remove(unwrapper_base& x);
}
}}} // namespace boost::python::converter
#endif // REGISTRY_DWA20011127_HPP

View File

@@ -0,0 +1,80 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SOURCE_DWA20011119_HPP
# define SOURCE_DWA20011119_HPP
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/mpl/select_type.hpp>
namespace boost { namespace python { namespace converter {
// source --
//
// This type generator (see
// ../../../more/generic_programming.html#type_generator) is used
// to select the argument type to use when converting T to a PyObject*
template <class T> struct source;
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Since for some strange reason temporaries can't be bound to const
// volatile references (8.5.3/5 in the C++ standard), we cannot use a
// const volatile reference as the standard for values and references.
template <class T>
struct source
{
typedef T const& type;
};
// This will handle the following:
// T const volatile& -> T const volatile&
// T volatile& -> T const volatile&
// T const& -> T const&
// T& -> T const&
template <class T>
struct source<T&>
{
typedef T const& type;
};
template <class T>
struct source<T*>
{
typedef T const* type;
};
template <class T>
struct source<T* const>
{
typedef T const* type;
};
// Deal with references to pointers
template <class T>
struct source<T*&>
{
typedef T const* type;
};
template <class T>
struct source<T* const&>
{
typedef T const* type;
};
# else
template <class T>
struct source
{
typedef typename add_reference<
typename add_const<T>::type
>::type type;
};
# endif
}}} // namespace boost::python::converter
#endif // SOURCE_DWA20011119_HPP

View File

@@ -0,0 +1,24 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SOURCE_HOLDER_DWA20011215_HPP
# define SOURCE_HOLDER_DWA20011215_HPP
namespace boost { namespace python { namespace converter {
struct source_holder_base
{
};
template <class T>
struct source_holder : source_holder_base
{
source_holder(T x) : value(x) {}
T value;
};
}}} // namespace boost::python::converter
#endif // SOURCE_HOLDER_DWA20011215_HPP

View File

@@ -0,0 +1,172 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef TARGET_DWA20011119_HPP
# define TARGET_DWA20011119_HPP
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/same_traits.hpp>
namespace boost { namespace python { namespace converter {
// target --
//
// This type generator (see
// ../../../more/generic_programming.html#type_generator) is used
// to select the return type of the appropriate converter for
// unwrapping a given type.
// Strategy:
//
// 1. reduce everything to a common, un-cv-qualified reference
// type where possible. This will save on registering many different
// converter types.
//
// 2. Treat built-in types specially: when unwrapping a value or
// constant reference to one of these, use a value for the target
// type. It will bind to a const reference if neccessary, and more
// importantly, avoids having to dynamically allocate room for
// an lvalue of types which can be cheaply copied.
//
// In the tables below, "cv" stands for the set of all possible
// cv-qualifications.
// Target Source
// int int
// int const& int
// int& int&
// int volatile& int volatile&
// int const volatile& int const volatile&
// On compilers supporting partial specialization:
//
// Target Source
// T T&
// T cv& T&
// T cv* T*
// T cv*const& T*
// T cv*& T*& <- should this be legal?
// T cv*volatile& T*& <- should this be legal?
// T cv*const volatile& T*& <- should this be legal?
// On others:
//
// Target Source
// T T&
// T cv& T cv&
// T cv* T cv*
// T cv*cv& T cv*cv&
// As you can see, in order to handle the same range of types without
// partial specialization, more converters need to be registered.
template <class T>
struct target
{
// Some pointer types are handled in a more sophisticated way on
// compilers supporting partial specialization.
BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_scalar<T>::value));
typedef typename mpl::select_type<
use_identity
, T
, typename add_reference<typename remove_cv<T>::type>::type
>::type type;
};
// When partial specialization is not present, we'll simply need to
// register many more converters.
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct target<T&>
{
typedef typename remove_cv<T>::type& type;
};
template <class T>
struct target<T*>
{
typedef typename remove_cv<T>::type* type;
};
// Handle T*-cv for completeness. Function arguments in a signature
// are never actually cv-qualified, but who knows how this might be
// used, or what compiler bugs may lurk?
template <class T>
struct target<T* const>
{
typedef typename remove_cv<T>::type* type;
};
template <class T>
struct target<T* volatile>
{
typedef typename remove_cv<T>::type* type;
};
template <class T>
struct target<T* const volatile>
{
typedef typename remove_cv<T>::type* type;
};
// non-const references to pointers should be handled by the
// specialization for T&, above.
template <class T>
struct target<T* const&>
{
typedef typename remove_cv<T>::type* type;
};
# endif
// Fortunately, we can handle T const& where T is an arithmetic type
// by explicit specialization. These specializations will cause value
// and const& arguments to be converted to values, rather than to
// references.
# define BOOST_PYTHON_UNWRAP_VALUE(T) \
template <> \
struct target<T> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const> \
{ \
typedef T type; \
}; \
template <> \
struct target<T volatile> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const volatile> \
{ \
typedef T type; \
}; \
template <> \
struct target<T const&> \
{ \
typedef T type; \
}
BOOST_PYTHON_UNWRAP_VALUE(char);
BOOST_PYTHON_UNWRAP_VALUE(unsigned char);
BOOST_PYTHON_UNWRAP_VALUE(signed char);
BOOST_PYTHON_UNWRAP_VALUE(unsigned int);
BOOST_PYTHON_UNWRAP_VALUE(signed int);
BOOST_PYTHON_UNWRAP_VALUE(unsigned short);
BOOST_PYTHON_UNWRAP_VALUE(signed short);
BOOST_PYTHON_UNWRAP_VALUE(unsigned long);
BOOST_PYTHON_UNWRAP_VALUE(signed long);
BOOST_PYTHON_UNWRAP_VALUE(char const*);
}}} // namespace boost::python::converter
#endif // TARGET_DWA20011119_HPP

View File

@@ -0,0 +1,200 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef TYPE_ID_DWA20011127_HPP
# define TYPE_ID_DWA20011127_HPP
# include <boost/config.hpp>
# include <boost/python/export.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/python/export.hpp>
# include <boost/operators.hpp>
# include <typeinfo>
# include <iosfwd>
# include <cstring>
namespace boost { namespace python { namespace converter {
// a portable mechanism for identifying types at runtime across modules.
namespace detail
{
template <class T> class dummy;
}
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so use typeid(x).name() instead. It's not
// yet clear what the best default strategy is.
# if defined(__GNUC__) && __GNUC__ >= 3
# define BOOST_PYTHON_TYPE_ID_NAME
# endif
# if 1
struct type_id_t : totally_ordered<type_id_t>
{
enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 };
# ifdef BOOST_PYTHON_TYPE_ID_NAME
typedef char const* base_id_t;
# else
typedef std::type_info const* base_id_t;
# endif
type_id_t(base_id_t, decoration decoration);
bool operator<(type_id_t const& rhs) const;
bool operator==(type_id_t const& rhs) const;
friend BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&);
private:
decoration m_decoration;
base_id_t m_base_type;
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct is_reference_to_const
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T>
struct is_reference_to_const<T const&>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct is_reference_to_volatile
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T>
struct is_reference_to_volatile<T volatile&>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
# else
template <typename V>
struct is_const_help
{
typedef typename mpl::select_type<
is_const<V>::value
, type_traits::yes_type
, type_traits::no_type
>::type type;
};
template <typename V>
struct is_volatile_help
{
typedef typename mpl::select_type<
is_volatile<V>::value
, type_traits::yes_type
, type_traits::no_type
>::type type;
};
template <typename V>
typename is_const_help<V>::type reference_to_const_helper(V&);
type_traits::no_type
reference_to_const_helper(...);
template <class T>
struct is_reference_to_const
{
static T t;
BOOST_STATIC_CONSTANT(
bool, value
= sizeof(reference_to_const_helper(t)) == sizeof(type_traits::yes_type));
};
template <typename V>
typename is_volatile_help<V>::type reference_to_volatile_helper(V&);
type_traits::no_type reference_to_volatile_helper(...);
template <class T>
struct is_reference_to_volatile
{
static T t;
BOOST_STATIC_CONSTANT(
bool, value
= sizeof(reference_to_volatile_helper(t)) == sizeof(type_traits::yes_type));
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
inline type_id_t type_id(detail::dummy<T>* = 0)
{
return type_id_t(
# ifdef BOOST_PYTHON_TYPE_ID_NAME
typeid(T).name()
# else
&typeid(T)
# endif
, type_id_t::decoration(
(is_const<T>::value || is_reference_to_const<T>::value
? type_id_t::const_ : 0)
| (is_volatile<T>::value || is_reference_to_volatile<T>::value
? type_id_t::volatile_ : 0)
| (is_reference<T>::value ? type_id_t::reference : 0)
)
);
}
inline type_id_t::type_id_t(base_id_t base_t, decoration decoration)
: m_decoration(decoration)
, m_base_type(base_t)
{
}
inline bool type_id_t::operator<(type_id_t const& rhs) const
{
return m_decoration < rhs.m_decoration
|| m_decoration == rhs.m_decoration
# ifdef BOOST_PYTHON_TYPE_ID_NAME
&& std::strcmp(m_base_type, rhs.m_base_type) < 0;
# else
&& m_base_type->before(*rhs.m_base_type);
# endif
}
inline bool type_id_t::operator==(type_id_t const& rhs) const
{
return m_decoration == rhs.m_decoration
# ifdef BOOST_PYTHON_TYPE_ID_NAME
&& !std::strcmp(m_base_type, rhs.m_base_type);
# else
&& *m_base_type == *rhs.m_base_type;
# endif
}
# else
// This is the type which is used to identify a type
typedef char const* type_id_t;
// This is a workaround for a silly MSVC bug
// Converts a compile-time type to its corresponding runtime identifier.
template <class T>
type_id_t type_id(detail::dummy<T>* = 0)
{
return typeid(T).name();
}
# endif
struct BOOST_PYTHON_EXPORT type_id_before
{
bool operator()(type_id_t const& x, type_id_t const& y) const;
};
BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream&, type_id_t const&);
}}} // namespace boost::python::converter
#endif // TYPE_ID_DWA20011127_HPP

View File

@@ -0,0 +1,192 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAP_BASE_DWA20011130_HPP
# define UNWRAP_BASE_DWA20011130_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrapper.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrapper;
struct BOOST_PYTHON_EXPORT body;
struct BOOST_PYTHON_EXPORT unwrap_base : handle
{
public: // member functions
inline unwrap_base(PyObject* source, body*, handle& prev);
inline unwrap_base(PyObject* source, body*);
inline PyObject* source() const;
private: // data members
PyObject* m_source;
};
// These converters will be used by the function wrappers. They don't
// manage any resources, but are instead linked into a chain which is
// managed by an instance of unwrap_ or wrap_.
template <class T>
struct unwrap_more_ : unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev);
// invoke the conversion or throw an exception if unsuccessful
T operator*();
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source);
private: // helper functions
// Return the unwrapper which will convert the given Python object
// to T, or 0 if no such converter exists
static unwrapper_base* lookup(PyObject*);
private:
// unspecified storage which may be allocated by the unwrapper to
// do value conversions.
mutable void* m_storage;
friend class unwrapper<T>;
};
// specialization for PyObject*
template <>
struct unwrap_more_<PyObject*>
: unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, m_unwrapper, prev)
{
}
// invoke the conversion or throw an exception if unsuccessful
PyObject* operator*()
{
return source();
}
bool convertible(PyObject*) const
{
return true;
}
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source)
: unwrap_base(source, m_unwrapper)
{
}
private:
static BOOST_PYTHON_EXPORT unwrapper_base* m_unwrapper;
};
template <class T>
struct unwrap_ : unwrap_more_<T>
{
unwrap_(PyObject* source);
~unwrap_();
};
//
// implementations
//
inline unwrap_base::unwrap_base(PyObject* source, body* body, handle& prev)
: handle(body, prev)
, m_source(source)
{
}
inline unwrap_base::unwrap_base(PyObject* source, body* body)
: handle(body)
, m_source(source)
{
}
inline PyObject* unwrap_base::source() const
{
return m_source;
}
template <class T>
inline unwrapper_base* unwrap_more_<T>::lookup(PyObject* source)
{
// Find the converters registered for T and get a unwrapper
// appropriate for the source object
return registration<T>::unwrapper(source);
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, lookup(source), prev)
, m_storage(0)
{
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source)
: unwrap_base(source, lookup(source))
, m_storage(0)
{
}
# if 0
template <>
inline unwrap_more_<PyObject*>::unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, m_unwrapper, prev)
{
}
template <>
inline unwrap_more_<PyObject*>::unwrap_more_(PyObject* source)
: unwrap_base(source, m_unwrapper)
{
}
template <>
inline PyObject* unwrap_more_<PyObject*>::operator*()
{
return source();
}
template <>
inline bool unwrap_more_<PyObject*>::convertible(PyObject*) const
{
return true;
}
# endif
template <class T>
inline unwrap_<T>::unwrap_(PyObject* source)
: unwrap_more_<T>(source)
{
}
template <class T>
T unwrap_more_<T>::operator*()
{
return static_cast<unwrapper<T>*>(
get_body())->do_conversion(this);
}
template <class T>
unwrap_<T>::~unwrap_()
{
destroy();
}
}}} // namespace boost::python::converter
#endif // UNWRAP_BASE_DWA20011130_HPP

View File

@@ -0,0 +1,53 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAPPER_DWA2001127_HPP
# define UNWRAPPER_DWA2001127_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrap.hpp>
# include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrap_more_;
// Abstract base for all unwrappers of Ts
template <class T>
struct unwrapper : unwrapper_base
{
public:
unwrapper();
T do_conversion(unwrap_more_<T> const* handle) const;
private:
virtual T convert(PyObject*, void*&) const = 0;
private: // body required interface implementation
void destroy_handle(handle*) const {}
};
//
// implementations
//
template <class T>
unwrapper<T>::unwrapper()
: unwrapper_base(type_id<T>())
{
}
// We could think about making this virtual in an effort to get its
// code generated in the module where the unwrapper is defined, but
// it's not clear that it's a good tradeoff.
template <class T>
T unwrapper<T>::do_conversion(unwrap_more_<T> const* handle) const
{
return convert(handle->source(), handle->m_storage);
}
}}} // namespace boost::python::converter
#endif // UNWRAPPER_DWA2001127_HPP

View File

@@ -0,0 +1,25 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef UNWRAPPER_BASE_DWA20011215_HPP
# define UNWRAPPER_BASE_DWA20011215_HPP
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT unwrapper_base : body
{
public:
unwrapper_base(type_id_t); // registers
~unwrapper_base(); // unregisters
virtual bool convertible(PyObject*) const = 0;
};
}}} // namespace boost::python::converter
#endif // UNWRAPPER_BASE_DWA20011215_HPP

View File

@@ -0,0 +1,145 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef WRAP_DWA2001127_HPP
# define WRAP_DWA2001127_HPP
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/wrapper.hpp>
# include <boost/python/export.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <cassert>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_EXPORT wrapper_base;
template <class T> struct wrapper;
struct wrap_base : handle
{
public: // member functions
wrap_base(body*, handle& prev);
wrap_base(body*);
PyObject* release();
public: // accessor, really only for wrappers
PyObject*& target() const;
protected:
void hold_result(PyObject*) const;
private:
mutable PyObject* m_target;
};
template <class T>
struct wrap_more_ : wrap_base
{
protected:
typedef T source_t;
public: // member functions
wrap_more_(handle& prev);
PyObject* operator()(source_t) const;
protected: // constructor for wrap_<T>, below
wrap_more_();
private: // helper functions
static wrapper_base* lookup();
private:
friend class wrapper<T>;
};
template <class T>
struct wrap_ : wrap_more_<T>
{
typedef typename wrap_more_<T>::source_t source_t;
public: // member functions
wrap_();
~wrap_();
};
//
// implementations
//
inline wrap_base::wrap_base(body* body, handle& prev)
: handle(body, prev),
m_target(0)
{
}
inline wrap_base::wrap_base(body* body)
: handle(body),
m_target(0)
{
}
inline PyObject*& wrap_base::target() const
{
return m_target;
}
inline void wrap_base::hold_result(PyObject* p) const
{
assert(m_target == 0);
m_target = p;
}
inline PyObject* wrap_base::release()
{
PyObject* result = m_target;
m_target = 0;
return result;
}
template <class T>
inline wrapper_base* wrap_more_<T>::lookup()
{
// Find the converters registered for T and get a wrapper
// appropriate for the source object
return registration<T>::wrapper();
}
template <class T>
inline wrap_more_<T>::wrap_more_(handle& prev)
: wrap_base(lookup(), prev)
{
}
template <class T>
PyObject* wrap_more_<T>::operator()(source_t x) const
{
return static_cast<wrapper<T>*>(
get_body())->do_conversion(*this, source_holder<T>(x));
}
template <class T>
wrap_more_<T>::wrap_more_()
: wrap_base(lookup())
{
}
template <class T>
wrap_<T>::wrap_()
: wrap_more_<T>()
{
}
template <class T>
wrap_<T>::~wrap_()
{
destroy();
}
}}} // namespace boost::python::converter
#endif // WRAP_DWA2001127_HPP

View File

@@ -0,0 +1,69 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef WRAPPER_DWA2001127_HPP
# define WRAPPER_DWA2001127_HPP
# include <boost/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <boost/python/export.hpp>
namespace boost { namespace python { namespace converter {
struct source_holder_base;
struct wrap_base;
template <class T> struct wrap_more_;
struct BOOST_PYTHON_EXPORT wrapper_base : body
{
public:
wrapper_base(type_id_t); // registers
~wrapper_base(); // unregisters
virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0;
};
template <class T>
struct wrapper : wrapper_base
{
public:
wrapper();
PyObject* do_conversion(wrap_base const&, source_holder_base const&) const;
// This does the actual conversion
virtual PyObject* convert(T source) const = 0;
};
//
// implementations
//
template <class T>
wrapper<T>::wrapper()
: wrapper_base(type_id<T>())
{
}
template <class T>
PyObject* wrapper<T>::do_conversion(wrap_base const& handle_, source_holder_base const& data_) const
{
// Casting pointers instead of references suppresses a CWPro7 bug.
wrap_more_<T> const& handle = *static_cast<wrap_more_<T> const*>(&handle_);
source_holder<T> const& data = *static_cast<source_holder<T> const*>(&data_);
if (handle.target() == 0)
{
handle.hold_result(convert(data.value));
}
return handle.target();
}
}}} // namespace boost::python::converter
#endif // WRAPPER_DWA2001127_HPP

View File

@@ -0,0 +1,233 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for 5-argument member functions and 6-argument free
// functions by gen_arg_tuple_size.python
#ifndef ARG_TUPLE_SIZE_DWA20011201_HPP
# define ARG_TUPLE_SIZE_DWA20011201_HPP
namespace boost { namespace python { namespace detail {
// Computes (at compile-time) the number of elements that a Python
// argument tuple must have in order to be passed to a wrapped C++
// (member) function of the given type.
template <class F> struct arg_tuple_size;
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__BORLANDC__)
template <class R>
struct arg_tuple_size<R (*)()>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 0);
};
template <class R, class A1>
struct arg_tuple_size<R (*)(A1)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
};
template <class R, class A1, class A2>
struct arg_tuple_size<R (*)(A1, A2)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 2);
};
template <class R, class A1, class A2, class A3>
struct arg_tuple_size<R (*)(A1, A2, A3)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 3);
};
template <class R, class A1, class A2, class A3, class A4>
struct arg_tuple_size<R (*)(A1, A2, A3, A4)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 4);
};
template <class R, class A1, class A2, class A3, class A4, class A5>
struct arg_tuple_size<R (*)(A1, A2, A3, A4, A5)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 5);
};
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
struct arg_tuple_size<R (*)(A1, A2, A3, A4, A5, A6)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 6);
};
template <class R, class A0>
struct arg_tuple_size<R (A0::*)()>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
};
template <class R, class A0, class A1>
struct arg_tuple_size<R (A0::*)(A1)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 2);
};
template <class R, class A0, class A1, class A2>
struct arg_tuple_size<R (A0::*)(A1, A2)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 3);
};
template <class R, class A0, class A1, class A2, class A3>
struct arg_tuple_size<R (A0::*)(A1, A2, A3)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 4);
};
template <class R, class A0, class A1, class A2, class A3, class A4>
struct arg_tuple_size<R (A0::*)(A1, A2, A3, A4)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 5);
};
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
struct arg_tuple_size<R (A0::*)(A1, A2, A3, A4, A5)>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 6);
};
# else
// We will use the "sizeof() trick" to work around the lack of
// partial specialization in MSVC6 and its broken-ness in borland.
// See http://opensource.adobe.com or
// http://groups.yahoo.com/group/boost/message/5441 for
// more examples
// This little package is used to transmit the number of arguments
// from the helper functions below to the sizeof() expression below.
// Because we can never have an array of fewer than 1 element, we
// add 1 to n and then subtract 1 from the result of sizeof() below.
template <int n>
struct char_array
{
char elements[n+1];
};
// The following helper functions are never actually called, since
// they are only used within a sizeof() expression, but the type of
// their return value is used to discriminate between various free
// and member function pointers at compile-time.
template <class R>
char_array<0> arg_tuple_size_helper(R (*)());
template <class R, class A1>
char_array<1> arg_tuple_size_helper(R (*)(A1));
template <class R, class A1, class A2>
char_array<2> arg_tuple_size_helper(R (*)(A1, A2));
template <class R, class A1, class A2, class A3>
char_array<3> arg_tuple_size_helper(R (*)(A1, A2, A3));
template <class R, class A1, class A2, class A3, class A4>
char_array<4> arg_tuple_size_helper(R (*)(A1, A2, A3, A4));
template <class R, class A1, class A2, class A3, class A4, class A5>
char_array<5> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5));
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
char_array<6> arg_tuple_size_helper(R (*)(A1, A2, A3, A4, A5, A6));
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)());
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1));
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2));
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3));
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4));
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5));
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)() const);
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const);
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const);
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const);
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const);
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const);
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)() volatile);
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) volatile);
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) volatile);
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) volatile);
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) volatile);
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) volatile);
template <class R, class A0>
char_array<1> arg_tuple_size_helper(R (A0::*)() const volatile);
template <class R, class A0, class A1>
char_array<2> arg_tuple_size_helper(R (A0::*)(A1) const volatile);
template <class R, class A0, class A1, class A2>
char_array<3> arg_tuple_size_helper(R (A0::*)(A1, A2) const volatile);
template <class R, class A0, class A1, class A2, class A3>
char_array<4> arg_tuple_size_helper(R (A0::*)(A1, A2, A3) const volatile);
template <class R, class A0, class A1, class A2, class A3, class A4>
char_array<5> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4) const volatile);
template <class R, class A0, class A1, class A2, class A3, class A4, class A5>
char_array<6> arg_tuple_size_helper(R (A0::*)(A1, A2, A3, A4, A5) const volatile);
template <class F>
struct arg_tuple_size
{
// The sizeof() magic happens here
BOOST_STATIC_CONSTANT(std::size_t, value
= sizeof(arg_tuple_size_helper(F(0)).elements) - 1);
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
}}} // namespace boost::python::detail
#endif // ARG_TUPLE_SIZE_DWA20011201_HPP

View File

@@ -0,0 +1,27 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CALLER_DWA20011214_HPP
# define CALLER_DWA20011214_HPP
# include <boost/python/call.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace detail {
struct caller
{
typedef PyObject* result_type;
template <class F>
PyObject* operator()(F f, PyObject* args, PyObject* keywords)
{
return call(f, args, keywords);
}
};
}}} // namespace boost::python::detail
#endif // CALLER_DWA20011214_HPP

View File

@@ -0,0 +1,846 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for 5-argument member functions and 6-argument free
// functions by gen_returning.py
#ifndef RETURNING_DWA20011201_HPP
# define RETURNING_DWA20011201_HPP
//# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/config.hpp>
# include <boost/python/convert.hpp>
# include <boost/python/detail/none.hpp>
namespace boost { namespace python { namespace detail {
// Calling C++ from Python
template <class R>
struct returning
{
template <class A0>
static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
template <class A0>
static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
template <class A0>
static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
// missing const volatile type traits
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class A0>
static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( ((*c0).*pmf)() );
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( ((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5) );
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ )
{
// find the result converter
wrap<R> r;
return r( (*pf)() );
};
template <class A0>
static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
// find the result converter
wrap_more<R> r(c0);
if (!c0) return 0;
return r( (*pf)(*c0) );
};
template <class A0, class A1>
static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
// find the result converter
wrap_more<R> r(c1);
if (!c0) return 0;
return r( (*pf)(*c0, *c1) );
};
template <class A0, class A1, class A2>
static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
// find the result converter
wrap_more<R> r(c2);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2) );
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
// find the result converter
wrap_more<R> r(c3);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2, *c3) );
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
// find the result converter
wrap_more<R> r(c4);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2, *c3, *c4) );
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
// find the result converter
wrap_more<R> r(c5);
if (!c0) return 0;
return r( (*pf)(*c0, *c1, *c2, *c3, *c4, *c5) );
};
};
template <>
struct returning<void>
{
typedef void R;
template <class A0>
static PyObject* call(R (A0::*pmf)(), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
template <class A0>
static PyObject* call(R (A0::*pmf)() const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
template <class A0>
static PyObject* call(R (A0::*pmf)() volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
// missing const volatile type traits
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class A0>
static PyObject* call(R (A0::*pmf)() const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
((*c0).*pmf)();
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (A0::*pmf)(A1) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
((*c0).*pmf)(*c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (A0::*pmf)(A1, A2) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (A0::*pmf)(A1, A2, A3) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (A0::*pmf)(A1, A2, A3, A4, A5) const volatile, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0 const volatile&> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
((*c0).*pmf)(*c1, *c2, *c3, *c4, *c5);
return detail::none();
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
static PyObject* call(R (*pf)(), PyObject*, PyObject* /* keywords */ )
{
(*pf)();
return detail::none();
};
template <class A0>
static PyObject* call(R (*pf)(A0), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
if (!c0) return 0;
(*pf)(*c0);
return detail::none();
};
template <class A0, class A1>
static PyObject* call(R (*pf)(A0, A1), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
if (!c0) return 0;
(*pf)(*c0, *c1);
return detail::none();
};
template <class A0, class A1, class A2>
static PyObject* call(R (*pf)(A0, A1, A2), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2);
return detail::none();
};
template <class A0, class A1, class A2, class A3>
static PyObject* call(R (*pf)(A0, A1, A2, A3), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2, *c3);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2, *c3, *c4);
return detail::none();
};
template <class A0, class A1, class A2, class A3, class A4, class A5>
static PyObject* call(R (*pf)(A0, A1, A2, A3, A4, A5), PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0> c0(PyTuple_GET_ITEM(args, 0));
unwrap_more<A1> c1(PyTuple_GET_ITEM(args, 1), c0);
unwrap_more<A2> c2(PyTuple_GET_ITEM(args, 2), c1);
unwrap_more<A3> c3(PyTuple_GET_ITEM(args, 3), c2);
unwrap_more<A4> c4(PyTuple_GET_ITEM(args, 4), c3);
unwrap_more<A5> c5(PyTuple_GET_ITEM(args, 5), c4);
if (!c0) return 0;
(*pf)(*c0, *c1, *c2, *c3, *c4, *c5);
return detail::none();
};
};
}}} // namespace boost::python::detail
#endif // RETURNING_DWA20011201_HPP

View File

@@ -0,0 +1,20 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef EXPORT_DWA20011120_HPP
# define EXPORT_DWA20011120_HPP
# include <boost/config.hpp>
# include <boost/preprocessor/if.hpp>
# include <boost/preprocessor/cat.hpp>
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# ifndef BOOST_PYTHON_EXPORT
# define BOOST_PYTHON_EXPORT __declspec(dllimport)
# endif
# else
# define BOOST_PYTHON_EXPORT
# endif
#endif // EXPORT_DWA20011120_HPP

View File

@@ -0,0 +1,41 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_FUNCTION_DWA20011214_HPP
# define MAKE_FUNCTION_DWA20011214_HPP
# include <boost/bind.hpp>
# include <boost/python/object/function.hpp>
# include <boost/python/object/make_holder.hpp>
# include <boost/python/detail/caller.hpp>
# include <boost/mpl/size.hpp>
namespace boost { namespace python {
template <class F>
PyObject* make_function(F f)
{
return new object::function(
object::py_function(
bind<PyObject*>(detail::caller(), f, _1, _2)));
}
template <class T, class ArgList, class Generator>
PyObject* make_constructor(T* = 0, ArgList* = 0, Generator* = 0)
{
return new object::function(
object::py_function(
bind<PyObject*>(detail::caller()
, object::make_holder<
mpl::size<ArgList>::value
>::template apply<
T, Generator, ArgList
>::execute
, _1, _2)));
}
}} // namespace boost::python
#endif // MAKE_FUNCTION_DWA20011214_HPP

View File

@@ -0,0 +1,37 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MODULE_DWA2001128_HPP
# define MODULE_DWA2001128_HPP
# include <boost/config.hpp>
#if defined(_WIN32) || defined(__CYGWIN__)
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
extern "C" __declspec(dllexport) void init##name() \
{ \
/*boost::python::handle_exception(*/init_module_##name()/*)*/; \
} \
void init_module_##name()
#else
# define BOOST_PYTHON_MODULE_INIT(name) \
void init_module_##name(); \
extern "C" void init##name() \
{ \
/*boost::python::handle_exception(*/init_module_##name()/*)*/; \
} \
void init_module_##name()
#endif
namespace boost { namespace python {
}} // namespace boost::python
#endif // MODULE_DWA2001128_HPP

View File

@@ -0,0 +1,76 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CLASS_DWA20011214_HPP
# define CLASS_DWA20011214_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# include <boost/utility.hpp>
# include <boost/python/converter/type_id.hpp>
namespace boost { namespace python { namespace object {
template <class T> struct holder;
// Base class for all holders
struct BOOST_PYTHON_EXPORT holder_base : noncopyable
{
public:
holder_base(converter::type_id_t id);
virtual ~holder_base();
virtual bool held_by_value() const = 0;
holder_base* next() const;
converter::type_id_t type() const;
void install(PyObject* inst);
private:
converter::type_id_t m_type;
holder_base* m_next;
};
// Abstract base class which holds a Held, somehow. Provides a uniform
// way to get a pointer to the held object
template <class Held>
struct holder : holder_base
{
typedef Held held_type;
holder();
virtual Held* target() = 0;
};
// Each extension instance will be one of these
struct instance
{
PyObject_HEAD
holder_base* objects;
};
extern BOOST_PYTHON_EXPORT PyTypeObject class_metatype;
extern BOOST_PYTHON_EXPORT PyTypeObject class_type;
//
// implementation
//
inline holder_base* holder_base::next() const
{
return m_next;
}
inline converter::type_id_t holder_base::type() const
{
return m_type;
}
template <class Held>
holder<Held>::holder()
: holder_base(converter::type_id<Held>())
{
}
}}} // namespace boost::python::object
#endif // CLASS_DWA20011214_HPP

View File

@@ -0,0 +1,24 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONSTRUCT_DWA20011215_HPP
# define CONSTRUCT_DWA20011215_HPP
namespace boost { namespace python { namespace object {
template <class T, class ArgList>
struct construct
{
static
template <class
void operator()(PyObject* args, PyObject* keywords)
{
}
};
}}} // namespace boost::python::object
#endif // CONSTRUCT_DWA20011215_HPP

View File

@@ -0,0 +1,33 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef FORWARD_DWA20011215_HPP
# define FORWARD_DWA20011215_HPP
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
namespace boost { namespace python { namespace object {
// A little metaprogram which selects the type to pass through an
// intermediate forwarding function when the destination argument type
// is T.
template <class T>
struct forward
{
typedef typename mpl::select_type<
is_scalar<T>::value | is_reference<T>::value
, T
, reference_wrapper<
typename add_const<T>::type
>
>::type type;
};
}}} // namespace boost::python::object
#endif // FORWARD_DWA20011215_HPP

View File

@@ -0,0 +1,36 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef FUNCTION_DWA20011214_HPP
# define FUNCTION_DWA20011214_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/export.hpp>
# include <boost/function.hpp>
namespace boost { namespace python { namespace object {
// We use boost::function to avoid generating lots of virtual tables
typedef boost::function2<PyObject*, PyObject*, PyObject*> py_function;
struct BOOST_PYTHON_EXPORT function : PyObject
{
function(py_function);
~function();
PyObject* call(PyObject*, PyObject*) const;
private:
py_function m_fn;
};
extern BOOST_PYTHON_EXPORT PyTypeObject function_type;
//
// implementations
//
}}} // namespace boost::python::object
#endif // FUNCTION_DWA20011214_HPP

View File

@@ -0,0 +1,124 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_HOLDER_DWA20011215_HPP
# define MAKE_HOLDER_DWA20011215_HPP
# include <boost/mpl/at.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/python/object/class.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace object {
template <class T> struct undefined;
template <class UnaryMetaFunction, class T>
struct eval
{
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
// based on the (non-conforming) MSVC trick from MPL
template<bool>
struct unarymetafunction_vc : UnaryMetaFunction {};
// illegal C++ which causes VC to admit that unarymetafunction_vc
// can have a nested template:
template<>
struct unarymetafunction_vc<true>
{
template<class> struct apply;
};
typedef typename unarymetafunction_vc<
::boost::mpl::detail::msvc_never_true<UnaryMetaFunction>::value
>::template apply<T>::type type;
# else
typedef typename UnaryMetaFunction::template apply<T>::type type;
# endif
};
template <int nargs> struct make_holder;
template <>
struct make_holder<0>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
static void execute(
PyObject* p)
{
(new holder(p))->install(p);
}
};
};
template <>
struct make_holder<1>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
static void execute(
PyObject* p
, t0 a0)
{
(new holder(p, f0(a0)))->install(p);
}
};
};
template <>
struct make_holder<2>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
typedef typename mpl::at<1,ArgList>::type t1;
typedef typename forward<t1>::type f1;
static void execute(
PyObject* p, t0 a0, t1 a1)
{
(new holder(p, f0(a0), f1(a1)))->install(p);
}
};
};
template <>
struct make_holder<3>
{
template <class T, class Generator, class ArgList>
struct apply
{
typedef typename eval<Generator,T>::type holder;
typedef typename mpl::at<0,ArgList>::type t0;
typedef typename forward<t0>::type f0;
typedef typename mpl::at<1,ArgList>::type t1;
typedef typename forward<t1>::type f1;
typedef typename mpl::at<2,ArgList>::type t2;
typedef typename forward<t2>::type f2;
static void execute(
PyObject* p, t0 a0, t1 a1, t2 a2)
{
(new holder(p, f0(a0), f1(a1), f2(a2)))->install(p);
}
};
};
}}} // namespace boost::python::object
#endif // MAKE_HOLDER_DWA20011215_HPP

View File

@@ -0,0 +1,80 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef VALUE_HOLDER_DWA20011215_HPP
# define VALUE_HOLDER_DWA20011215_HPP
# include <boost/python/object/class.hpp>
namespace boost { namespace python { namespace object {
template <class Held>
struct value_holder : holder<Held>
{
// Forward construction to the held object
value_holder(PyObject*)
: m_held() {}
template <class A1>
value_holder(PyObject*, A1 a1)
: m_held(a1) {}
template <class A1, class A2>
value_holder(PyObject*, A1 a1, A2 a2)
: m_held(a1, a2) {}
template <class A1, class A2, class A3>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3)
: m_held(a1, a2, a3) {}
template <class A1, class A2, class A3, class A4>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4)
: m_held(a1, a2, a3, a4) {}
template <class A1, class A2, class A3, class A4, class A5>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
: m_held(a1, a2, a3, a4, a5) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
: m_held(a1, a2, a3, a4, a5, a6) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
: m_held(a1, a2, a3, a4, a5, a6, a7) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
: m_held(a1, a2, a3, a4, a5, a6, a7, a8) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
: m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
value_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
: m_held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
private: // required holder implementation
Held* target() { return &m_held; }
bool held_by_value() const { return true; }
private: // data members
Held m_held;
};
// A generator metafunction which can be passed to make_holder
struct value_holder_generator
{
template <class Held>
struct apply
{
typedef value_holder<Held> type;
};
};
}}} // namespace boost::python::object
#endif // VALUE_HOLDER_DWA20011215_HPP

View File

@@ -1,180 +0,0 @@
23 October 2003
Fixed bug where a class would appear more than one in the generated code.
6 October 2003
Fixed bug reported by Niall Douglas (using his patch) about UniqueInt not
appearing correctly with --multiple.
Added precompiled header support on windows systems (using #pragma hdrstop).
Suggested by Niall Douglas.
Fixed a bug with -I directive and AllFromHeader. Reported by Scott Snyder.
4 October 2003
Added return_self, thanks for Niall Douglas for pointing out that it was
missing.
Added --file-list, where you can pass a file where the pyste files are listed
one per line. Also suggested by Niall Douglas.
Documentation has been finally updated, after a long wait. Please let me know
if you spot any mistake!
2 October 2003
Scott Snyder found a typo in ClassExporter that prevented -= and *= operators
from being exported. Thanks Scott!
20 September 2003
Added return_by_value in the list of policies supported. Thanks to Niall
Douglas for the remainder.
19 September 2003
Better support for unnamed enums, plus they are by default exported to the
parent's namespace. Normal enums can have the same behaviour using the function
export_values on the Enum object. Feature requested by Niall Douglas.
10 September 2003
A new variable is accessible in the Pyste files: INTERFACE_FILE contains the
full path of the pyste file.
4 September 2003
Now it is possible to override protected and private pure virtual functions
in Python, as requested by Roman Yakovenko.
23 August 2003
Fixed bug where some Imports where not writing their include files.
Now whenever the declarations change, the cache files are rebuilt
automatically.
19 August 2003
Fixed a bug related to the generation of the bases<> template.
17 August 2003
Added support for insertion of user code in the generated code.
16 August 2003
Applied a patch by Gottfried Ganssauge that adds exception specifiers to
wrapper functions and pointer declarations. Thanks a lot Gottfried!!
Applied a patch by Prabhu Ramachandran that fixes ae problem with the
pure virtual method generation. Thanks again Prabhu!
10 August 2003
Support for incremental generation of the code has been added. This changes
how --multiple works; documentation of this new feature will follow. Thanks
to Prabhu Ramachandran, that saw the need for this feature and discussed a
solution.
Automatically convert \ to / in Windows systems before passing the paths to
gccxml.
Fixed a bug reported by Prabhu Ramachandran, where in some classes the virtual
methods were being definied incorrectly. Thanks a lot Prabhu!
7 July 2003
Applied 2 patches by Prabhu Ramachandran: a fix in the new --multiple method,
and two new functions "hold_with_shared_ptr" and its counterpart for auto_ptr.
Thanks a lot Prabhu!
Fixed a bug where the macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID was being
called multiple times for the same type.
Thanks to Gottfried Ganßauge for reporting this!
Fixed bug where using AllFromHeader didn't use bases<> when exporting
hierarchies.
Fixed the staticmethod bug.
5 July 2003
Changed how --multiple works: now it generates one cpp file for each pyste
file, makeing easier to integrate Pyste with build systems.
4 July 2003
Applied patch that solved a bug in ClassExporter and added a distutils install
script (install/setup.py), both contributed by Prabhu Ramachandran.
Thanks Prabhu!
2 July 2003
Jim Wilson found a bug where types like "char**" were being interpreted as
"char*". Thanks Jim!
16 June 2003
Thanks to discussions with David Abrahams and Roman Sulzhyk, some behaviours
have changed:
- If you export a derived class without exporting its base classes, the derived
class will explicitly export the bases's methods and attributes. Before, if
you were interested in the bases's methods, you had to export the base
classes too.
- Added a new function, no_override. When a member function is specified as
"no_override", no virtual wrappers are generated for it, improving
performance and letting the code more clean.
- There was a bug in which the policy of virtual member functions was being
ignored (patch by Roman Sulzhyk).
Thanks again to Roman Sulzhyk for the patches and discussion in the c++-sig.
4 June 2003
Major improvements in memory usage.
3 June 2003
Appliced a patch from Giulio Eulisse that allows unnamed enumerations to be
exported with an AllFromHeader construct. Thanks a lot Giulio!
2 June 2003
Added a new construct, add_method. See documentation.
23 May 2003
Support for global variables added.
Various bug fixes.
08 May 2003
Fixed bug where in a certain cases the GCCXMLParser would end up with multiple
declarations of the same class
22 Apr 2003
- Now shows a warning when the user tries to export a forward-declared class.
Forward-declared classes are ignored by the AllFromHeader construct.
- Fixed a bug where classes, functions and enums where being exported, even if
excluded from a AllFromHeader construct.
16 Apr 2003
Added a more generic (but ugly) code to declare the smart pointer converters.
07 Apr 2003
- Removed the warnings about forward declarations: it was not accurate enough.
Another strategy must be thought of.
- Fixed bug in the --multiple mode, where the order of the class instantiations
could end up wrong.
- Lots of fixes in the documentation, pointed out by Dirk Gerrits. Thanks Dirk!
- Fixed support for the return_opaque_pointer policy (the support macro was not
being declared).
06 Apr 2003
Support for the improved static data members support of Boost.Python.
05 Apr 2003
New option for generating the bindings: --multiple.
02 Apr 2003
Forward declarations are now detected and a warning is generated.
24 Mar 2003
Default policy for functions/methods that return const T& is now
return_value_policy<copy_const_reference>().
22 Mar 2003
Exporting virtual methods of the base classes in the derived classes too.
21 Mar 2003
Added manual support for boost::shared_ptr and std::auto_ptr (see doc).
19 Mar 2003
Added support for int, double, float and long operators acting as expected in
python.
14 Mar 2003
Fixed bug: Wrappers for protected and virtual methods were not being generated.

217
release_notes.txt Normal file
View File

@@ -0,0 +1,217 @@
2000-11-22 10:00
Ullrich fixed bug in operator_dispatcher<op_long>.
2000-11-21 10:00
Changed all class and function names into lower_case.
Ullrich updated documentation for operator wrapping.
2000-11-20 10:00
Ullrich renamed ExtensionClass:register_coerce() into
ExtensionClass:def_standard_coerce() and made it public
Ullrich improved shared_pod_manager.
2000-11-17 15:04
Changed allocation strategy of shared_pod_manager to make it portable.
Added pickling support + tests thanks to "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Added a specialization of Callback<const char*> to prevent unsafe usage.
Fixed Ullrich's operator_dispatcher refcount bug
Removed const char* return values from virtual functions in tests; that
usage was unsafe.
Ullrich changed Module::add() so that it steals a reference (fix of refcount bug)
Ullrich added operator_dispatcher::create() optimization
Ullrich changed design and implementation of TypeObjectBase::enable() (to eliminate low-level
code) and added shared_pod_manager optimization.
2000-11-15 12:01
Fixed refcount bugs in operator calls.
Added callback_adjust_refcount(PyObject*, Type<T>) to account for different ownership
semantics of Callback's return types and Caller's arguments (which both use from_python())
This bug caused refcount errors during operator calls.
Moved operator_dispatcher into extclass.cpp
Gave it shared ownership of the objects it wraps
Introduced sequence points in extension_class_coerce for exception-safety
UPPER_CASE_MACRO_NAMES
MixedCase template type argument names
Changed internal error reporting to use Python exceptions so we don't force the
user to link in iostreams code
Changed error return value of call_cmp to -1
Moved unwrap_* functions out of operator_dispatcher. This was transitional: when
I realized they didn't need to be declared in extclass.h I moved them out, but
now that operator_dispatcher itself is in extclass.cpp they could go back in.
Numerous formatting tweaks
Updated the BoundFunction::create() optimization and enabled it so it could actually be used!
2000-11-15 00:26
Made Ullrich's operators support work with MSVC
Cleaned up operators.h such that invalid define_operator<0> is no longer needed.
Ullrich created operators.h to support wrapping of C++ operators (including the "__r*__" forms).
He added several auxiliary classes to extclass.h and extclass.cpp (most importantly,
py::detail::operator_dispatcher and py::operators)
2000-11-13 22:29
removed obsolete ExtensionClassFromPython for good.
removed unused class ExtensionType forward declaration
2000-11-12 13:08
Added enum_as_int_converters for easier enum wrapping
Introduced new conversion namespace macros:
PY_BEGIN_CONVERSION_NAMESPACE,
PY_END_CONVERSION_NAMESPACE,
PY_CONVERSION
callback.h, gen_callback.py:
Added call() function so that a regular python function (as opposed to
method or other function-as-attribute) can be called.
Added newlines for readability.
class_wrapper.h:
Fixed a bug in add(), which allows non-method class attributes
Ullrich has added def_raw for simple varargs and keyword support.
Fixed version number check for __MWERKS__
Added tests for enums and non-method class attributes
objects.h/objects.cpp:
Added py::String operator*= and operator* for repetition
Change Dict::items(), keys(), and values() to return a List
Added template versions of set_item, etc., methods so that users can optionally
use C++ types that have to_python() functions as parameters.
Changed various Ptr by-value parameters to const Ptr&
======= Release =======
2000-11-06 0:22
Lots of documentation updates
added 4-argument template constructor to py::Tuple
added "add" member function to ClassWrapper<> to allow arbitrary Python
objects to be added to an extension class.
gen_all.py now generates support for n argument member functions and n+1
argument member functions at the suggestion of "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Added regression tests and re-ordered declare_base calls to verify that the
phantom base class issue is resolved.
2000-11-04 17:35
Integrated Ullrich Koethe's brilliant from_python_experiment for better
error-reporting in many cases.
extclass.h, gen_extclass.py:
removed special-case MSVC code
added much commentary
removed unused py_copy_to_new_value_holder
init_function.h, gen_init_function.py:
added missing 'template' keyword on type-dependent template member usage
removed special-case MSVC code
added much commentary
2000-11-04 0:36
Removed the need for the phantom base class that screwed up inheritance
hierarchies, introduced error-prone ordering dependencies, and complexified
logic in many places!
extclass.h: Added some explanatory comments, removed wasteful m_self member
of HeldInstance
extclass_demo.cpp: Added #pragmas which allow compilation in ansi strict
mode under Metrowerks
functions.h: Added virtual_function as part of phantom base class removal;
expanded commentary
pyptr.h: Added some missing 'typename's and a GCC workaround fix
subclass.cpp: Added missing string literal const_cast<>s.
2000-11-03 10:58
Fix friend function instantiation bug caught by Metrowerks (thanks
Metrowerks!)
Add proof-of-concept for one technique of wrapping function that return a
pointer
Worked around MSVC optimizer bug by writing to_python(double) and
to_python(float) out-of-line
2000-11-02 23:25
Add /Zm200 option to vc6_prj to deal with MSVC resource limitations
Remove conflicting /Ot option from vc6_prj release build
======= Release =======
2000-11-02 17:42
Added a fix for interactions between default virtual function
implementations and declare_base(). You still need to write your
declare_base() /after/ all member functions have been def()d for the two
classes concerned. Many, many thanks to Ullrich Koethe
<koethe@informatik.uni-hamburg.de> for all his work on this.
Added missing conversions:
to_python(float)
from_python(const char* const&)
from_python(const double&)
from_python(const float&)
Added a Regression test for a reference-counting bug thanks to Mark Evans
(<mark.evans@clarisay.com>)
const-ify ClassBase::getattr()
Add repr() function to Class<T>
Add to_python/from_python conversions for PyPtr<T>
Standardize set_item/get_item interfaces (instead of proxies) for Dict and List
Add Reprable<> template to newtypes.h
Fix a bug wherein the __module__ attribute would be lost for classes that have a
default virtual function implementation.
Remove extra ';' in module.cpp thanks to "Ralf W. Grosse-Kunstleve"
<rwgk@cci.lbl.gov>
Fix a bug in the code of example1.html

18
src/converter/body.cpp Normal file
View File

@@ -0,0 +1,18 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
// default implementation is a no-op. Most handles will not hold any
// data that needs to be managed. Unwrap objects which convert
// by-value are an exception. Fortunately, the concrete body subclass
// has that knowledge.
void body::destroy_handle(handle*) const
{
}
}}} // namespace boost::python::converter

35
src/converter/handle.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/handle.hpp>
#include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
bool handle::convertible() const
{
for (handle const* p = this; p != 0; p = p->m_next)
{
if (p->m_body == 0)
return false;
}
return true;
}
void handle::destroy()
{
// Recurse down the chain releasing from tail to head
if (m_next != 0)
m_next->destroy();
// Our body knows how to destroy us. If we never got a body,
// there's nothing to do.
if (m_body)
m_body->destroy_handle(this);
}
// void handle::dummy::nonnull() {}
}}} // namespace boost::python::converter

170
src/converter/registry.cpp Normal file
View File

@@ -0,0 +1,170 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
# include <boost/python/converter/unwrapper.hpp>
# include <boost/python/converter/wrapper.hpp>
# include <map>
# include <list>
# include <algorithm>
# include <stdexcept>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
namespace boost { namespace python { namespace converter {
namespace // <unnamed>
{
typedef std::map<type_id_t, registry::entry, type_id_before> registry_t;
registry_t& entries()
{
static registry_t registry;
return registry;
}
} // namespace <unnamed>
namespace registry
{
entry* find(type_id_t type)
{
return &entries()[type];
}
entry::entry()
: m_wrapper(0)
{
}
namespace // <unnamed>
{
// A UnaryFunction type which deletes its argument
struct delete_item
{
template <class T>
void operator()(T* x) const
{
delete x;
}
};
// A UnaryFunction type which returns true iff its argument is a
// unwrapper which can convert the given Python object.
struct convertible
{
convertible(PyObject* p)
: m_p(p)
{}
bool operator()(unwrapper_base* converter) const
{
return converter->convertible(m_p);
}
PyObject* m_p;
};
}
entry::~entry()
{
}
unwrapper_base* entry::unwrapper(PyObject* p) const
{
unwrappers::const_iterator q =
std::find_if(m_unwrappers.begin(), m_unwrappers.end(), convertible(p));
return q == m_unwrappers.end() ? 0 : *q;
}
wrapper_base* entry::wrapper() const
{
return m_wrapper;
}
entry::unwrappers::iterator entry::find(unwrapper_base const& x)
{
return std::find(m_unwrappers.begin(), m_unwrappers.end(), &x);
}
void entry::insert(unwrapper_base& x)
{
unwrappers::iterator p = this->find(x);
assert(p == m_unwrappers.end());
if (p != m_unwrappers.end())
{
throw std::runtime_error(
"trying to register unrapper which is already registered");
}
m_unwrappers.push_back(&x);
}
void entry::remove(unwrapper_base& x)
{
unwrappers::iterator p = find(x);
// Be sure we're not removing a converter which hasn't been
// registered.
assert(p != m_unwrappers.end());
if (p == m_unwrappers.end())
{
throw std::runtime_error(
"trying to unregister unwrapper which is not registered");
}
m_unwrappers.erase(p);
}
void entry::insert(wrapper_base& x)
{
assert(m_wrapper == 0); // we have a problem otherwise
if (m_wrapper != 0)
{
throw std::runtime_error(
"trying to register wrapper for a type which already has a registered wrapper");
}
m_wrapper = &x;
}
void entry::remove(wrapper_base& x)
{
assert(m_wrapper == &x);
if (m_wrapper != &x)
{
throw std::runtime_error(
"trying to unregister a wrapper which is not registered");
}
m_wrapper = 0;
}
void insert(wrapper_base& w)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting wrapper for " << w.key() << std::endl;
# endif
find(w.key())->insert(w);
}
void insert(unwrapper_base& u)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting unwrapper for " << u.key() << std::endl;
# endif
find(u.key())->insert(u);
}
void remove(wrapper_base& w)
{
find(w.key())->remove(w);
}
void remove(unwrapper_base& u)
{
find(u.key())->remove(u);
}
} // namespace registry
}}} // namespace boost::python::converter

67
src/converter/type_id.cpp Normal file
View File

@@ -0,0 +1,67 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/type_id.hpp>
#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT
# include <ostream>
#else
# include <ostream.h>
#endif
namespace boost { namespace python { namespace converter {
#if 1
bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const
{
return x < y;
}
BOOST_PYTHON_EXPORT std::ostream& operator<<(std::ostream& os, type_id_t const& x)
{
# ifdef BOOST_PYTHON_TYPE_ID_NAME
os << x.m_base_type;
# else
os << x.m_base_type->name();
# endif
// VC6 mistakenly distinguishes typeid(X) from typeid(X const)
// from typeid(X&)... so the name is already correct. I have it
// from Jason Shirk that VC7.0 has the same bug but it will be
// fixed in 7.1
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
if (x.m_decoration & type_id_t::const_)
os << " const";
if (x.m_decoration & type_id_t::volatile_)
os << " volatile";
if (x.m_decoration & type_id_t::reference)
os << "&";
# endif
return os;
}
#else
bool type_id_before::operator()(type_id_t const& x, type_id_t const& y) const
{
for (;;)
{
if (*y == 0)
{
return 0;
}
else if (*x == 0)
{
return 1;
}
else if (*x != *y)
{
return *x < *y;
}
++x;
++y;
}
}
#endif
}}} // namespace boost::python::converter

35
src/converter/unwrap.cpp Normal file
View File

@@ -0,0 +1,35 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/unwrap.hpp>
namespace boost { namespace python { namespace converter {
namespace
{
struct pyobject_unwrapper : unwrapper_base
{
pyobject_unwrapper();
bool convertible(PyObject*) const;
};
pyobject_unwrapper static_unwrapper;
pyobject_unwrapper::pyobject_unwrapper()
: unwrapper_base(type_id<PyObject*>())
{
}
bool pyobject_unwrapper::convertible(PyObject*) const
{
return true;
}
}
BOOST_PYTHON_EXPORT unwrapper_base*
unwrap_more_<PyObject*>::m_unwrapper = &static_unwrapper;
}}} // namespace boost::python::converter

View File

@@ -0,0 +1,23 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/unwrapper.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/type_traits/same_traits.hpp>
namespace boost { namespace python { namespace converter {
unwrapper_base::unwrapper_base(type_id_t key)
: body(key)
{
registry::insert(*this);
}
unwrapper_base::~unwrapper_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter

29
src/converter/wrapper.cpp Normal file
View File

@@ -0,0 +1,29 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/wrapper.hpp>
namespace boost { namespace python { namespace converter {
wrapper_base::wrapper_base(type_id_t type)
: body(type)
{
// static assertions for target<T>. These would go in a header,
// but Metrowerks only respects BOOST_STATIC_ASSERT if it is in an
// instantiated function
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#else
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
registry::insert(*this);
}
wrapper_base::~wrapper_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter

82
src/gen_call.py Normal file
View File

@@ -0,0 +1,82 @@
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# This work was funded in part by Lawrence Berkeley National Labs
from gen_function import *
import string
header = '''// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for %d-argument member functions and %d-argument free
// functions by gen_call.py
#ifndef CALL_DWA20011214_HPP
# define CALL_DWA20011214_HPP
# include <boost/python/detail/returning.hpp>
namespace boost { namespace python {
'''
_cv_qualifiers = ('', ' const', ' volatile', ' const volatile')
def gen_call(member_function_args, free_function_args = None):
if free_function_args is None:
free_function_args = member_function_args + 1
return (header % (member_function_args, free_function_args)
+ gen_functions(
'''template <class R%(, class A%n%)>
PyObject* call(R (*f)(%(A%n%:, %)), PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
''', free_function_args)
+
'''// Member functions
'''
+ reduce(lambda x,y: x+y
, map(lambda cv:
gen_functions(
'''template <class R, class A0%(, class A%+%)>
PyObject* call(R (A0::*f)(%(A%+%:, %))%1, PyObject* args, PyObject* keywords)
{
return detail::returning<R>::call(f, args, keywords);
}
'''
, member_function_args, cv)
, _cv_qualifiers))
+
'''
}} // namespace boost::python
#endif // CALL_DWA20011214_HPP
''')
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
member_function_args = 5
free_function_args = 6
else:
member_function_args = int(sys.argv[1])
if len(sys.argv) > 2:
free_function_args = int(sys.argv[2])
else:
free_function_args = member_function_args
print gen_call(member_function_args, free_function_args)

191
src/gen_returning.py Normal file
View File

@@ -0,0 +1,191 @@
# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# This work was funded in part by Lawrence Berkeley National Labs
from gen_function import *
import string
header = '''// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// This work was funded in part by Lawrence Berkeley National Labs
//
// This file generated for %d-argument member functions and %d-argument free
// functions by gen_returning.py
'''
body_sections = (
'''
#ifndef RETURNING_DWA20011201_HPP
# define RETURNING_DWA20011201_HPP
//# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/config.hpp>
# include <boost/python/convert.hpp>
# include <boost/python/detail/none.hpp>
namespace boost { namespace python { namespace detail {
// Calling C++ from Python
template <class R>
struct returning
{
''',
'''
''',
''' // Free functions
''',
'''};
template <>
struct returning<void>
{
typedef void R;
''',
'''
''',
'''
// Free functions
''',
'''};
}}} // namespace boost::python::detail
#endif // RETURNING_DWA20011201_HPP
''')
#'
member_function = ''' template <class A0%(, class A%+%)>
static PyObject* call(R (A0::*pmf)(%(A%+%:, %))%1, PyObject* args, PyObject* /* keywords */ )
{
// check that each of the arguments is convertible
unwrap<A0%1&> c0(PyTuple_GET_ITEM(args, 0));
%( unwrap_more<A%+> c%+(PyTuple_GET_ITEM(args, %+), c%n);
%)
%[r%: // find the result converter
wrap_more<R> r(c%n);
%] if (!c0) return 0;
%[r%:return r( %]((*c0).*pmf)(%(*c%+%:, %))%[r%: )%];%[v%:
return detail::none();%]
};
'''
free_function = '''%{ template <%(class A%n%:, %)>
%} static PyObject* call(R (*pf)(%(A%n%:, %)), PyObject*%{ args%}, PyObject* /* keywords */ )
{%{
// check that each of the arguments is convertible
%}%( unwrap%{_more%}<A%n> c%n(PyTuple_GET_ITEM(args, %n)%{, c%-%});
%)%[r%:
// find the result converter
wrap%{_more%}<R> r%{(c%-)%};%]%{
if (!c0) return 0;%}
%[r%:return r( %](*pf)(%(*c%n%:, %))%[r%: )%];%[v%:
return detail::none();%]
};
'''
def _returns_value(key, n, args, value):
if key == 'r':
return value
# pass the value through gen_function again for recursive expansion
# return apply(gen_function, (value, n) + args
# , {'fill': _returns_value})
else:
assert key == 'v'
return ''
def _returns_void(key, n, args, value):
if key == 'v':
return value
else:
assert key == 'r'
# return the empty string, ignoring the value
return ''
_cv_qualifiers = ('', ' const', ' volatile', ' const volatile')
_prefix = {
# ' const': '''
# // missing cv-qualified -> cv-unqualified member pointer conversions
# # if defined(__MWERKS__) && __MWERKS__ <=0x2406 || defined(BOOST_MSVC) && BOOST_MSVC <= 1200 || defined(__BORLANDC__)
# ''',
' const volatile': '''
// missing const volatile type traits
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''};
def gen_returning(member_function_args, free_function_args = None):
if free_function_args is None:
free_function_args = member_function_args + 1
return_none = ''';
return detail::none();'''
return (header % (member_function_args, free_function_args)
+ body_sections[0]
#
# functions returning results
#
+ reduce(lambda x,y: x+y
, map(lambda cv:
_prefix.get(cv,'')
+ gen_functions(member_function,
member_function_args, cv,
fill = _returns_value) + '\n'
, _cv_qualifiers))
+ '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''
## endif // missing cv-qualified -> cv-unqualified member pointer conversions
#'''
# free functions
+ gen_functions(free_function, free_function_args, fill = _returns_value)
+ body_sections[3]
#
# functions returning void
#
+ reduce(lambda x,y: x+y
, map(lambda cv:
_prefix.get(cv,'')
+ gen_functions(member_function,
member_function_args, cv, fill =
_returns_void) + '\n'
, _cv_qualifiers))
+ '''# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
'''
## endif // missing cv-qualified -> cv-unqualified member pointer conversions
#'''
# free functions
+ gen_functions(free_function, free_function_args, fill = _returns_void)
+ body_sections[6]
)
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
member_function_args = 5
free_function_args = 6
else:
member_function_args = int(sys.argv[1])
if len(sys.argv) > 2:
free_function_args = int(sys.argv[2])
else:
free_function_args = member_function_args
print gen_returning(member_function_args, free_function_args)

117
src/object/class.cpp Normal file
View File

@@ -0,0 +1,117 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/export.hpp>
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/object/class.hpp>
namespace boost { namespace python { namespace object {
holder_base::holder_base(converter::type_id_t id)
: m_type(id)
, m_next(0)
{
}
holder_base::~holder_base()
{
}
BOOST_PYTHON_EXPORT PyTypeObject class_metatype = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"Boost.Python.class",
PyType_Type.tp_basicsize,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyType_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0,
// PyType_GenericNew /* tp_new */
};
BOOST_PYTHON_EXPORT PyTypeObject class_type = {
PyObject_HEAD_INIT(&class_metatype)
0,
"Boost.Python.instance",
sizeof(instance),
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyBaseObject_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew
};
void holder_base::install(PyObject* self)
{
assert(self->ob_type->ob_type == &class_metatype);
m_next = ((instance*)self)->objects;
((instance*)self)->objects = this;
}
}}} // namespace boost::python::object

95
src/object/function.cpp Normal file
View File

@@ -0,0 +1,95 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/object/function.hpp>
namespace boost { namespace python { namespace object {
function::function(py_function implementation)
: m_fn(implementation)
{
PyObject* p = this;
PyObject_INIT(p, &function_type);
}
function::~function()
{
}
PyObject* function::call(PyObject* args, PyObject* keywords) const
{
return m_fn(args, keywords);
}
extern "C"
{
// Stolen from Python's funcobject.c
static PyObject *
function_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
if (obj == Py_None)
obj = NULL;
return PyMethod_New(func, obj, type);
}
static void
function_dealloc(PyObject* p)
{
delete static_cast<function*>(p);
}
static PyObject *
function_call(PyObject *func, PyObject *arg, PyObject *kw)
{
return static_cast<function*>(func)->call(arg, kw);
}
}
PyTypeObject function_type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"Boost.Python.function",
sizeof(function),
0,
(destructor)function_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, //(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
function_call, /* tp_call */
0, /* tp_str */
0, // PyObject_GenericGetAttr, /* tp_getattro */
0, // PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */
0, /* tp_doc */
0, // (traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, // func_memberlist, /* tp_members */
0, //func_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
function_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0,
0 /* tp_new */
};
}}} // namespace boost::python::object

39
test/complicated.hpp Normal file
View File

@@ -0,0 +1,39 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef COMPLICATED_DWA20011215_HPP
# define COMPLICATED_DWA20011215_HPP
# include <iostream>
# include "simple_type.hpp"
struct complicated
{
complicated(simple const&, int = 0);
~complicated();
int get_n() const;
char* s;
int n;
};
inline complicated::complicated(simple const&s, int n)
: s(s.s), n(n)
{
std::cout << "constructing complicated: " << this->s << ", " << n << std::endl;
}
inline complicated::~complicated()
{
std::cout << "destroying complicated: " << this->s << ", " << n << std::endl;
}
inline int complicated::get_n() const
{
return n;
}
#endif // COMPLICATED_DWA20011215_HPP

286
test/m1.cpp Normal file
View File

@@ -0,0 +1,286 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// Seems to be neccessary to suppress an ICE with MSVC
#include "boost/mpl/comparison/less.hpp"
#include "simple_type.hpp"
#include "complicated.hpp"
#include <boost/python/converter/wrapper.hpp>
#include <boost/python/converter/unwrapper.hpp>
#include <boost/python/module.hpp>
#include <boost/python/convert.hpp>
#include <boost/python/object/value_holder.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/make_function.hpp>
#include <boost/mpl/type_list.hpp>
#include <string.h>
extern "C" void
dealloc(PyObject* self)
{
PyObject_Del(self);
}
struct NoddyObject : PyObject
{
int x;
};
PyTypeObject NoddyType = {
PyObject_HEAD_INIT(NULL)
0,
"Noddy",
sizeof(NoddyObject),
0,
dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
struct SimpleObject : PyObject
{
simple x;
};
PyTypeObject SimpleType = {
PyObject_HEAD_INIT(NULL)
0,
"Simple",
sizeof(SimpleObject),
0,
dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
extern "C" PyObject*
new_noddy(PyObject* self, PyObject* args)
{
NoddyObject* noddy;
if (!PyArg_ParseTuple(args,":new_noddy"))
return NULL;
noddy = PyObject_New(NoddyObject, &NoddyType);
noddy->x = 42;
return (PyObject*)noddy;
}
extern "C" PyObject*
new_simple(PyObject* self, PyObject* args)
{
SimpleObject* simple;
if (!PyArg_ParseTuple(args,":new_simple"))
return NULL;
simple = PyObject_New(SimpleObject, &SimpleType);
simple->x.s = "hello, world";
return (PyObject*)simple;
}
static PyMethodDef methods[] = {
{ "new_noddy", new_noddy, METH_VARARGS },
{ "new_simple", new_simple, METH_VARARGS },
{NULL, NULL}
};
struct int_wrapper
: boost::python::converter::wrapper<int const&>
{
PyObject* convert(int const& x) const
{
return PyInt_FromLong(x);
}
};
struct simple_wrapper
: boost::python::converter::wrapper<simple const&>
{
PyObject* convert(simple const& x) const
{
SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
p->x = x;
return p;
}
};
struct simple_ref_wrapper
: boost::python::converter::wrapper<simple&>
{
PyObject* convert(simple& x) const
{
SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
p->x = x;
return p;
}
};
struct native_int_unwrapper
: boost::python::converter::unwrapper<int>
{
bool convertible(PyObject* p) const
{
return PyInt_Check(p);
}
int convert(PyObject* p, void*&) const
{
return PyInt_AsLong(p);
}
};
struct noddy_int_unwrapper
: boost::python::converter::unwrapper<int>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &NoddyType;
}
int convert(PyObject* p, void*&) const
{
return static_cast<NoddyObject*>(p)->x;
}
};
struct noddy_int_ref_unwrapper
: boost::python::converter::unwrapper<int&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &NoddyType;
}
int& convert(PyObject* p, void*&) const
{
return static_cast<NoddyObject*>(p)->x;
}
};
struct simple_ref_unwrapper
: boost::python::converter::unwrapper<simple&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
struct simple_const_ref_unwrapper
: boost::python::converter::unwrapper<simple const&>
{
bool convertible(PyObject* p) const
{
return p->ob_type == &SimpleType;
}
simple const& convert(PyObject* p, void*&) const
{
return static_cast<SimpleObject*>(p)->x;
}
};
int f(simple const& s)
{
return strlen(s.s);
}
simple const& g(simple const& x)
{
return x;
}
BOOST_PYTHON_MODULE_INIT(m1)
{
PyObject* m1 = Py_InitModule(const_cast<char*>("m1"), methods);
static int_wrapper wrap_int;
static simple_wrapper wrap_simple;
static native_int_unwrapper unwrap_int1;
static noddy_int_unwrapper unwrap_int2;
static noddy_int_ref_unwrapper unwrap_int3;
static simple_ref_unwrapper unwrap_simple;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// These compilers will need additional converters
static simple_const_ref_unwrapper unwrap_simple_const_ref;
static simple_ref_wrapper wrap_simple_ref;
#endif
// Not quite right
if (PyType_Ready(&boost::python::object::class_metatype) < 0)
return;
if (PyType_Ready(&boost::python::object::class_type) < 0)
return;
Py_INCREF(&boost::python::object::class_type);
PyObject* d = PyModule_GetDict(m1);
if (d == NULL)
return;
if (PyDict_SetItemString(
d, "xclass", (PyObject *)&boost::python::object::class_metatype) < 0)
return;
if (PyDict_SetItemString(
d, "xinst", (PyObject *)&boost::python::object::class_type) < 0)
return;
if (PyDict_SetItemString(
d, "f", boost::python::make_function(f)) < 0)
return;
if (PyDict_SetItemString(
d, "g", boost::python::make_function(g)) < 0)
return;
if (PyDict_SetItemString(
d, "get_n", boost::python::make_function(&complicated::get_n)) < 0)
return;
if (PyDict_SetItemString(
d, "init1"
, boost::python::make_constructor<
complicated
, boost::mpl::type_list<simple const&,int>
, boost::python::object::value_holder_generator>()
) < 0)
return;
if (PyDict_SetItemString(
d, "init2"
, boost::python::make_constructor<
complicated
, boost::mpl::type_list<simple const&>
, boost::python::object::value_holder_generator>()
) < 0)
return;
}
#include "module_tail.cpp"

197
test/m2.cpp Normal file
View File

@@ -0,0 +1,197 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/convert.hpp>
#include <boost/python/module.hpp>
#include "simple_type.hpp"
using boost::python::wrap;
using boost::python::unwrap;
extern "C" {
PyObject*
unwrap_simple(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
boost::python::unwrap<simple> in(p);
if (!in)
return 0;
simple x = *in;
return PyString_FromString(x.s);
};
PyObject*
unwrap_simple_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<simple&> in(p);
if (!in)
return 0;
simple& x = *in;
return PyString_FromString(x.s);
};
PyObject*
unwrap_simple_const_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<simple const&> in(p);
if (!in)
return 0;
simple const& x = *in;
return PyString_FromString(x.s);
};
PyObject*
unwrap_int(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<int> in(p);
if (!in)
return 0;
int x = *in;
return PyInt_FromLong(x);
};
PyObject*
unwrap_int_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<int&> in(p);
if (!in)
return 0;
int& x = *in;
return PyInt_FromLong(x);
};
PyObject*
unwrap_int_const_ref(PyObject* self, PyObject* args)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
unwrap<int&> in(p);
if (!in)
return 0;
int const& x = *in;
return PyInt_FromLong(x);
};
// -------------------
}
template <class T> struct xxxx;
template <class T>
PyObject*
rewrap(PyObject* self, PyObject* args, xxxx<T>* = 0)
{
PyObject* p;
if (!PyArg_ParseTuple(args, "O", &p))
return 0;
boost::python::unwrap<T> in(p);
if (!in)
return 0;
boost::python::wrap<T> out;
if (!out)
return 0;
T x = *in;
return out(x);
}
extern "C"
{
PyObject*
wrap_simple(PyObject* self, PyObject* args)
{
return rewrap<simple>(self, args);
};
PyObject*
wrap_simple_ref(PyObject* self, PyObject* args)
{
return rewrap<simple&>(self, args);
};
PyObject*
wrap_simple_const_ref(PyObject* self, PyObject* args)
{
return rewrap<simple const&>(self, args);
};
PyObject*
wrap_int(PyObject* self, PyObject* args)
{
return rewrap<int>(self, args);
};
PyObject*
wrap_int_ref(PyObject* self, PyObject* args)
{
return rewrap<int&>(self, args);
};
PyObject*
wrap_int_const_ref(PyObject* self, PyObject* args)
{
return rewrap<int const&>(self, args);
};
}
PyMethodDef initial_methods[] =
{
{ "unwrap_int", unwrap_int, METH_VARARGS, 0 },
{ "unwrap_int_ref", unwrap_int_ref, METH_VARARGS, 0 },
{ "unwrap_int_const_ref", unwrap_int_const_ref, METH_VARARGS, 0 },
{ "unwrap_simple", unwrap_simple, METH_VARARGS, 0 },
{ "unwrap_simple_ref", unwrap_simple_ref, METH_VARARGS, 0 },
{ "unwrap_simple_const_ref", unwrap_simple_const_ref, METH_VARARGS, 0 },
{ "wrap_int", wrap_int, METH_VARARGS, 0 },
{ "wrap_int_ref", wrap_int_ref, METH_VARARGS, 0 },
{ "wrap_int_const_ref", wrap_int_const_ref, METH_VARARGS, 0 },
{ "wrap_simple", wrap_simple, METH_VARARGS, 0 },
{ "wrap_simple_ref", wrap_simple_ref, METH_VARARGS, 0 },
{ "wrap_simple_const_ref", wrap_simple_const_ref, METH_VARARGS, 0 },
{ 0, 0, 0, 0 }
};
BOOST_PYTHON_MODULE_INIT(m2)
{
Py_InitModule(const_cast<char*>("m2"), initial_methods);
}
#include "module_tail.cpp"

39
test/module_tail.cpp Normal file
View File

@@ -0,0 +1,39 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#if defined(_WIN32)
# ifdef __MWERKS__
# pragma ANSI_strict off
# endif
# include <windows.h>
# ifdef __MWERKS__
# pragma ANSI_strict reset
# endif
extern "C" BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved );
# ifdef BOOST_MSVC
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
# endif
BOOL WINAPI DllMain(
HINSTANCE, //hDllInst
DWORD fdwReason,
LPVOID // lpvReserved
)
{
# ifdef BOOST_MSVC
_set_se_translator(structured_exception_translator);
# endif
(void)fdwReason; // warning suppression.
return 1;
}
#endif // _WIN32

90
test/newtest.py Normal file
View File

@@ -0,0 +1,90 @@
"""
>>> from m1 import *
>>> from m2 import *
>>> n = new_noddy()
>>> s = new_simple()
>>> unwrap_int(n)
42
>>> unwrap_int_ref(n)
42
>>> unwrap_int_const_ref(n)
42
>>> unwrap_simple(s)
'hello, world'
>>> unwrap_simple_ref(s)
'hello, world'
>>> unwrap_simple_const_ref(s)
'hello, world'
>>> unwrap_int(5)
5
Can't get a reference to a built-in integer object
>>> try:
... unwrap_int_ref(7)
... except: pass
... else: print 'no exception'
>>> try:
... unwrap_int_const_ref(9)
... except: pass
... else: print 'no exception'
>>> wrap_int(n)
42
try: wrap_int_ref(n)
... except: pass
... else: print 'no exception'
>>> wrap_int_const_ref(n)
42
>>> unwrap_simple_ref(wrap_simple(s))
'hello, world'
>>> unwrap_simple_ref(wrap_simple_ref(s))
'hello, world'
>>> unwrap_simple_ref(wrap_simple_const_ref(s))
'hello, world'
>>> f(s)
12
>>> unwrap_simple(g(s))
'hello, world'
>>> f(g(s))
12
>>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n})
>>> c = C(s, 99)
>>> c.get_n()
99
>>> D = xclass('D', (xinst,), {'__init__': init2, 'get_n': get_n})
>>> d = D(s)
>>> d.get_n()
0
"""
def run(args = None):
import m1,m2
import string
import re
import sys
if args is not None:
sys.argv = args
import sys
import doctest
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
sys.exit(run()[0])

14
test/simple_type.hpp Normal file
View File

@@ -0,0 +1,14 @@
// Copyright David Abrahams 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SIMPLE_TYPE_DWA2001128_HPP
# define SIMPLE_TYPE_DWA2001128_HPP
struct simple
{
char* s;
};
#endif // SIMPLE_TYPE_DWA2001128_HPP