mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 04:42:28 +00:00
Compare commits
8 Commits
boost-0.9.
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
480aaf6400 | ||
|
|
26b15fe373 | ||
|
|
eadcc79089 | ||
|
|
35fd3dfaa1 | ||
|
|
3505ac2516 | ||
|
|
946ed17ae1 | ||
|
|
a4747eb10a | ||
|
|
4d6772dac2 |
57
Jamfile
Normal file
57
Jamfile
Normal 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
308
doc/new-conversions.html
Normal 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<T>);
|
||||
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 <class Derived>
|
||||
struct add_some_functions
|
||||
{
|
||||
friend <i>return-type</i> some_function1(..., Derived <i>cv-*-&-opt</i>, ...);
|
||||
friend <i>return-type</i> some_function2(..., Derived <i>cv-*-&-opt</i>, ...);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_template : add_some_functions<some_template<T> >
|
||||
{
|
||||
};
|
||||
</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 "will the
|
||||
conversion succeed?" 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<T></tt> and
|
||||
<tt>unwrap<T></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<T></tt> object for efficiency. For
|
||||
example, if the handle is an <tt>unwrap<Foo&></tt> object,
|
||||
the <tt>entry</tt> for <tt>Foo&</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<double>
|
||||
const&</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 "active"
|
||||
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 "dynamically-determined
|
||||
vtable" 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&
|
||||
T* const&
|
||||
T&
|
||||
T const&
|
||||
T
|
||||
std::auto_ptr<T>&
|
||||
std::auto_ptr<T>
|
||||
std::auto_ptr<T> const&
|
||||
boost::shared_ptr<T>&
|
||||
boost::shared_ptr<T>
|
||||
boost::shared_ptr<T> const&
|
||||
</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&</tt>. <font color="#ff0000">What about conversions
|
||||
to values like the tuple->vector example above? It seems to me
|
||||
that we don't want to make a <tt>vector<double>&</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
|
||||
"<tt>_more</tt>" class which does the same job, but has a
|
||||
trivial destructor. Instead of asking each "<tt>_more</tt>"
|
||||
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
111
doc/new-conversions.txt
Normal 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.
|
||||
210
include/boost/python/call.hpp
Normal file
210
include/boost/python/call.hpp
Normal 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
|
||||
|
||||
82
include/boost/python/convert.hpp
Normal file
82
include/boost/python/convert.hpp
Normal 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
|
||||
46
include/boost/python/converter/body.hpp
Normal file
46
include/boost/python/converter/body.hpp
Normal 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
|
||||
56
include/boost/python/converter/class.hpp
Normal file
56
include/boost/python/converter/class.hpp
Normal 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
|
||||
91
include/boost/python/converter/handle.hpp
Normal file
91
include/boost/python/converter/handle.hpp
Normal 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
|
||||
83
include/boost/python/converter/registration.hpp
Normal file
83
include/boost/python/converter/registration.hpp
Normal 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
|
||||
74
include/boost/python/converter/registry.hpp
Normal file
74
include/boost/python/converter/registry.hpp
Normal 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
|
||||
80
include/boost/python/converter/source.hpp
Normal file
80
include/boost/python/converter/source.hpp
Normal 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
|
||||
24
include/boost/python/converter/source_holder.hpp
Normal file
24
include/boost/python/converter/source_holder.hpp
Normal 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
|
||||
172
include/boost/python/converter/target.hpp
Normal file
172
include/boost/python/converter/target.hpp
Normal 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
|
||||
200
include/boost/python/converter/type_id.hpp
Normal file
200
include/boost/python/converter/type_id.hpp
Normal 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
|
||||
192
include/boost/python/converter/unwrap.hpp
Normal file
192
include/boost/python/converter/unwrap.hpp
Normal 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
|
||||
53
include/boost/python/converter/unwrapper.hpp
Normal file
53
include/boost/python/converter/unwrapper.hpp
Normal 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
|
||||
25
include/boost/python/converter/unwrapper_base.hpp
Normal file
25
include/boost/python/converter/unwrapper_base.hpp
Normal 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
|
||||
145
include/boost/python/converter/wrap.hpp
Normal file
145
include/boost/python/converter/wrap.hpp
Normal 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
|
||||
69
include/boost/python/converter/wrapper.hpp
Normal file
69
include/boost/python/converter/wrapper.hpp
Normal 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
|
||||
233
include/boost/python/detail/arg_tuple_size.hpp
Normal file
233
include/boost/python/detail/arg_tuple_size.hpp
Normal 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
|
||||
|
||||
27
include/boost/python/detail/caller.hpp
Normal file
27
include/boost/python/detail/caller.hpp
Normal 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
|
||||
846
include/boost/python/detail/returning.hpp
Normal file
846
include/boost/python/detail/returning.hpp
Normal 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
|
||||
|
||||
20
include/boost/python/export.hpp
Normal file
20
include/boost/python/export.hpp
Normal 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
|
||||
41
include/boost/python/make_function.hpp
Normal file
41
include/boost/python/make_function.hpp
Normal 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
|
||||
37
include/boost/python/module.hpp
Normal file
37
include/boost/python/module.hpp
Normal 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
|
||||
76
include/boost/python/object/class.hpp
Normal file
76
include/boost/python/object/class.hpp
Normal 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
|
||||
24
include/boost/python/object/construct.hpp
Normal file
24
include/boost/python/object/construct.hpp
Normal 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
|
||||
33
include/boost/python/object/forward.hpp
Normal file
33
include/boost/python/object/forward.hpp
Normal 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
|
||||
36
include/boost/python/object/function.hpp
Normal file
36
include/boost/python/object/function.hpp
Normal 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
|
||||
124
include/boost/python/object/make_holder.hpp
Normal file
124
include/boost/python/object/make_holder.hpp
Normal 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
|
||||
80
include/boost/python/object/value_holder.hpp
Normal file
80
include/boost/python/object/value_holder.hpp
Normal 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
|
||||
180
pyste/NEWS
180
pyste/NEWS
@@ -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
217
release_notes.txt
Normal 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
18
src/converter/body.cpp
Normal 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
35
src/converter/handle.cpp
Normal 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
170
src/converter/registry.cpp
Normal 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
67
src/converter/type_id.cpp
Normal 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
35
src/converter/unwrap.cpp
Normal 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
|
||||
23
src/converter/unwrapper.cpp
Normal file
23
src/converter/unwrapper.cpp
Normal 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
29
src/converter/wrapper.cpp
Normal 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
82
src/gen_call.py
Normal 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
191
src/gen_returning.py
Normal 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
117
src/object/class.cpp
Normal 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
95
src/object/function.cpp
Normal 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
39
test/complicated.hpp
Normal 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
286
test/m1.cpp
Normal 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
197
test/m2.cpp
Normal 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
39
test/module_tail.cpp
Normal 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
90
test/newtest.py
Normal 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
14
test/simple_type.hpp
Normal 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
|
||||
Reference in New Issue
Block a user