mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 04:42:28 +00:00
Compare commits
196 Commits
svn-branch
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c75c27e7ca | ||
|
|
4eadbb299e | ||
|
|
ac20fcca63 | ||
|
|
cd00f7b01f | ||
|
|
d4b215a66b | ||
|
|
1a13387012 | ||
|
|
291c36df05 | ||
|
|
bed2c8a371 | ||
|
|
e65ca4ccac | ||
|
|
f9e6933840 | ||
|
|
5134fb2ec1 | ||
|
|
3a86a69964 | ||
|
|
c6fd3c47a4 | ||
|
|
a365fa6109 | ||
|
|
160451b210 | ||
|
|
2f6e3cc09d | ||
|
|
d05cc7ccec | ||
|
|
ccfd4acbda | ||
|
|
6a6084ed0e | ||
|
|
0dbb780a2f | ||
|
|
e6efa6e13e | ||
|
|
76768120d4 | ||
|
|
7d6ff83760 | ||
|
|
5bec0d2d98 | ||
|
|
aad05325a6 | ||
|
|
6e7f1bc257 | ||
|
|
634d0848c8 | ||
|
|
b7e1059227 | ||
|
|
e7904fa67a | ||
|
|
e38bc7cbce | ||
|
|
b211f8a096 | ||
|
|
b4a1a6c688 | ||
|
|
6cb4b790b9 | ||
|
|
a245bdbc2a | ||
|
|
e63451a9e7 | ||
|
|
e552607c95 | ||
|
|
c7f1c5e29c | ||
|
|
37b6e22321 | ||
|
|
6e6ae18aab | ||
|
|
9f3cda0ac3 | ||
|
|
f646975c36 | ||
|
|
801cae13ac | ||
|
|
f1ae502b1f | ||
|
|
f2e34d4836 | ||
|
|
3c6a8d718f | ||
|
|
08eb28f7b8 | ||
|
|
24509a21d4 | ||
|
|
4f41a10fef | ||
|
|
26aa8b69f9 | ||
|
|
819db1524f | ||
|
|
8ad7d06ec6 | ||
|
|
606898f569 | ||
|
|
76c6adf1cf | ||
|
|
e504c3cd46 | ||
|
|
884b59a0b3 | ||
|
|
a32dedd16c | ||
|
|
ff2b37f6e3 | ||
|
|
4328ae1d8d | ||
|
|
88372000b5 | ||
|
|
081150b477 | ||
|
|
1364b97b88 | ||
|
|
7c33a46a76 | ||
|
|
8b88e9f727 | ||
|
|
91f0728b55 | ||
|
|
7a71cea92a | ||
|
|
29a855813d | ||
|
|
66da2339d4 | ||
|
|
294254efbb | ||
|
|
188597ecaf | ||
|
|
d04f613c41 | ||
|
|
25320cd0e0 | ||
|
|
00b4f09e8a | ||
|
|
fb8d9edfdf | ||
|
|
349b9bb2bf | ||
|
|
cbff11296b | ||
|
|
dc462cdc1f | ||
|
|
22024e7c1f | ||
|
|
ebb0145256 | ||
|
|
c3215d0ba5 | ||
|
|
da83f20a28 | ||
|
|
ad4b0fff56 | ||
|
|
62b90206e8 | ||
|
|
38ac4fe849 | ||
|
|
fa7b6591cf | ||
|
|
fde432601a | ||
|
|
0c954dde27 | ||
|
|
b5a86a9045 | ||
|
|
ef7c437957 | ||
|
|
8158a509c9 | ||
|
|
dc520c6c32 | ||
|
|
907033f725 | ||
|
|
533a005764 | ||
|
|
9ee563b864 | ||
|
|
748c118ea8 | ||
|
|
69e69a77d8 | ||
|
|
5a40cec1ed | ||
|
|
01bcd460da | ||
|
|
2a96c9f9ee | ||
|
|
f610e31a87 | ||
|
|
4ec0b61de5 | ||
|
|
c7d7cec281 | ||
|
|
c4775a581e | ||
|
|
591eaeaafb | ||
|
|
1f45a846c6 | ||
|
|
db943b4109 | ||
|
|
098eadefe0 | ||
|
|
13b2e072d2 | ||
|
|
c068a300f4 | ||
|
|
60b91ac678 | ||
|
|
c979ab01af | ||
|
|
012b4025a4 | ||
|
|
ff04d9f03c | ||
|
|
ed34cd45f1 | ||
|
|
7dc8fab961 | ||
|
|
14acb1af8c | ||
|
|
678fa006de | ||
|
|
f5416ebce0 | ||
|
|
585063f6e1 | ||
|
|
494f12090f | ||
|
|
55321b8778 | ||
|
|
a6b0fa546a | ||
|
|
33ea0dbdee | ||
|
|
a559480716 | ||
|
|
bdbd9a0f5f | ||
|
|
945344b3cd | ||
|
|
5759ce9ba0 | ||
|
|
a350b666fa | ||
|
|
041409d715 | ||
|
|
98b31ed073 | ||
|
|
00cea4ff83 | ||
|
|
617bcdac9f | ||
|
|
116b3db1d1 | ||
|
|
53d2398e06 | ||
|
|
dd0e42cf72 | ||
|
|
b0d6d40c2a | ||
|
|
2d568b1c0f | ||
|
|
5b13e75fa5 | ||
|
|
23725680c9 | ||
|
|
f49141f71e | ||
|
|
fdff5e33b3 | ||
|
|
149cc499ed | ||
|
|
2e145ea916 | ||
|
|
1edec9ff89 | ||
|
|
a559a371b1 | ||
|
|
7d29c6a0f7 | ||
|
|
5ad51c36fb | ||
|
|
03dd2883f7 | ||
|
|
7208104122 | ||
|
|
405710e635 | ||
|
|
f6ba5a41da | ||
|
|
af6cfd0ea8 | ||
|
|
a3f822b7d3 | ||
|
|
afdaa4d0d8 | ||
|
|
bf5eec727e | ||
|
|
f82151f925 | ||
|
|
4b926b7c7f | ||
|
|
4aa4f1c3b3 | ||
|
|
71aff9f0e8 | ||
|
|
a40daca9ef | ||
|
|
0b97d9bae5 | ||
|
|
28e6a84acb | ||
|
|
fc62d3b44e | ||
|
|
b06d9e50eb | ||
|
|
1d4427c056 | ||
|
|
51d60a6035 | ||
|
|
f5fa4a460a | ||
|
|
977841a7f3 | ||
|
|
b000c75947 | ||
|
|
f3d9193743 | ||
|
|
0d04bf8e34 | ||
|
|
1d17690f69 | ||
|
|
4d19be8ea4 | ||
|
|
1d4dfdf271 | ||
|
|
f24a95c917 | ||
|
|
e508842da6 | ||
|
|
b0d9bbc0b1 | ||
|
|
6238770324 | ||
|
|
a8641c69cc | ||
|
|
7d9332e94f | ||
|
|
7ca17b7bd9 | ||
|
|
e5670d5e3c | ||
|
|
826c1bd894 | ||
|
|
7ea7f87a9f | ||
|
|
b91d11431d | ||
|
|
ff31b16285 | ||
|
|
81cf5333c3 | ||
|
|
9dca983e33 | ||
|
|
0f43a2fe9b | ||
|
|
ecdf8e1591 | ||
|
|
8a5de60b33 | ||
|
|
8637e270a9 | ||
|
|
c278310d1b | ||
|
|
7f58e66754 | ||
|
|
4e27f8de27 | ||
|
|
445b0438a2 | ||
|
|
23441191c3 |
57
Jamfile
57
Jamfile
@@ -1,57 +0,0 @@
|
||||
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 ;
|
||||
142
build/Jamfile
Normal file
142
build/Jamfile
Normal file
@@ -0,0 +1,142 @@
|
||||
# (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.
|
||||
#
|
||||
# Boost.Python build and test Jamfile
|
||||
#
|
||||
# To run all tests quietly: jam test
|
||||
# To run all tests with verbose output: jam -sPYTHON_TEST_ARGS=-v test
|
||||
#
|
||||
# Declares the following targets:
|
||||
# 1. libboost_python, a static link library to be linked with all
|
||||
# Boost.Python modules
|
||||
#
|
||||
# 2. pairs of test targets of the form <name>.test and <name>.run
|
||||
# <name>.test runs the test when it is out-of-date, and the "test"
|
||||
# pseudotarget depends on it. <name>.run runs
|
||||
# a test unconditionally, and can be used to force a test to run.. Each
|
||||
# test target builds one or more Boost.Python modules and runs a Python
|
||||
# script to test them. The test names are:
|
||||
#
|
||||
# from ../test
|
||||
#
|
||||
# comprehensive - a comprehensive test of Boost.Python features
|
||||
#
|
||||
# from ../example:
|
||||
# abstract -
|
||||
# getting_started1 -
|
||||
# getting_started2 -
|
||||
# simple_vector -
|
||||
# do_it_yourself_convts -
|
||||
# pickle1 -
|
||||
# pickle2 -
|
||||
# pickle3 -
|
||||
#
|
||||
# dvect1 -
|
||||
# dvect2 -
|
||||
# ivect1 -
|
||||
# ivect2 -
|
||||
# noncopyable -
|
||||
#
|
||||
# subproject-specific environment/command-line variables:
|
||||
#
|
||||
# PYTHON - How to invoke the Python interpreter. Defaults to "python"
|
||||
#
|
||||
# PYTHON_ROOT - Windows only: where Python is installed. Defaults to "c:/tools/python"
|
||||
#
|
||||
# PYTHON_VERSION - Version of Python. Defaults to "2.1" on Windows, "1.5" on Unix
|
||||
#
|
||||
# PYTHON_TEST_ARGS - specifies arguments to be passed to test scripts on
|
||||
# the command line. "-v" can be useful if you want to
|
||||
# see the output of successful tests.
|
||||
#
|
||||
# PYTHON_VECT_ITERATIONS - specifies the number of test iterations to use for
|
||||
# the dvect and ivect tests above.
|
||||
|
||||
# declare the location of this subproject relative to the root
|
||||
subproject libs/python/build ;
|
||||
|
||||
# bring in the rules for python
|
||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include <module@>python.jam ;
|
||||
|
||||
#######################
|
||||
local rule bpl-test ( test-name : sources + )
|
||||
{
|
||||
boost-python-test $(test-name) : $(sources) <lib>libboost_python ;
|
||||
}
|
||||
|
||||
#######################
|
||||
|
||||
#
|
||||
# Declare the boost python static link library
|
||||
#
|
||||
|
||||
# Base names of the source files for libboost_python
|
||||
local CPP_SOURCES =
|
||||
types classes conversions extension_class functions
|
||||
init_function module_builder objects cross_module ;
|
||||
|
||||
lib libboost_python : ../src/$(CPP_SOURCES).cpp
|
||||
# requirements
|
||||
: $(BOOST_PYTHON_INCLUDES)
|
||||
<shared-linkable>true
|
||||
$(PYTHON_PROPERTIES) ;
|
||||
|
||||
|
||||
############# comprehensive module and test ###########
|
||||
bpl-test boost_python_test
|
||||
: ../test/comprehensive.cpp ;
|
||||
|
||||
boost-python-runtest comprehensive
|
||||
: ../test/comprehensive.py <lib>boost_python_test <lib>libboost_python ;
|
||||
|
||||
############# simple tests from ../example ############
|
||||
|
||||
local rule boost-python-example-runtest ( name )
|
||||
{
|
||||
bpl-test $(name)
|
||||
: ../example/$(name).cpp ;
|
||||
|
||||
boost-python-runtest $(name)
|
||||
: ../example/test_$(name).py <lib>$(name) ;
|
||||
}
|
||||
|
||||
|
||||
boost-python-example-runtest abstract ;
|
||||
boost-python-example-runtest getting_started1 ;
|
||||
boost-python-example-runtest getting_started2 ;
|
||||
boost-python-example-runtest simple_vector ;
|
||||
boost-python-example-runtest do_it_yourself_convts ;
|
||||
boost-python-example-runtest pickle1 ;
|
||||
boost-python-example-runtest pickle2 ;
|
||||
boost-python-example-runtest pickle3 ;
|
||||
|
||||
|
||||
bpl-test ivect : ../example/ivect.cpp ;
|
||||
bpl-test dvect : ../example/dvect.cpp ;
|
||||
bpl-test noncopyable_export : ../example/noncopyable_export.cpp ;
|
||||
bpl-test noncopyable_import : ../example/noncopyable_import.cpp ;
|
||||
|
||||
############## cross-module tests from ../example ##########
|
||||
|
||||
# A simple rule to build a test which depends on multiple modules in the PYTHONPATH
|
||||
local rule boost-python-multi-example-runtest ( test-name : modules + )
|
||||
{
|
||||
boost-python-runtest $(test-name)
|
||||
: ../example/tst_$(test-name).py <lib>$(modules) <lib>libboost_python
|
||||
: : : $(PYTHON_VECT_ITERATIONS) ;
|
||||
}
|
||||
|
||||
PYTHON_VECT_ITERATIONS ?= 10 ;
|
||||
|
||||
boost-python-multi-example-runtest dvect1 : ivect dvect ;
|
||||
boost-python-multi-example-runtest dvect2 : ivect dvect ;
|
||||
|
||||
boost-python-multi-example-runtest ivect1 : ivect dvect ;
|
||||
boost-python-multi-example-runtest ivect2 : ivect dvect ;
|
||||
|
||||
boost-python-multi-example-runtest
|
||||
noncopyable : noncopyable_import noncopyable_export ;
|
||||
|
||||
@@ -1,308 +0,0 @@
|
||||
<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>
|
||||
@@ -1,111 +0,0 @@
|
||||
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.
|
||||
@@ -1,210 +0,0 @@
|
||||
// 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
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
// 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
|
||||
@@ -1,46 +0,0 @@
|
||||
// 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
|
||||
@@ -1,56 +0,0 @@
|
||||
// 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
|
||||
@@ -1,91 +0,0 @@
|
||||
// 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
|
||||
@@ -1,83 +0,0 @@
|
||||
// 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
|
||||
@@ -1,74 +0,0 @@
|
||||
// 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
|
||||
@@ -1,80 +0,0 @@
|
||||
// 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
|
||||
@@ -1,24 +0,0 @@
|
||||
// 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
|
||||
@@ -1,172 +0,0 @@
|
||||
// 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
|
||||
@@ -1,200 +0,0 @@
|
||||
// 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
|
||||
@@ -1,192 +0,0 @@
|
||||
// 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
|
||||
@@ -1,53 +0,0 @@
|
||||
// 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
|
||||
@@ -1,25 +0,0 @@
|
||||
// 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
|
||||
@@ -1,145 +0,0 @@
|
||||
// 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
|
||||
@@ -1,69 +0,0 @@
|
||||
// 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
|
||||
64
include/boost/python/detail/base_object.hpp
Normal file
64
include/boost/python/detail/base_object.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||
|
||||
#ifndef BASE_OBJECT_DWA051600_H_
|
||||
# define BASE_OBJECT_DWA051600_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/signatures.hpp> // really just for type<>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <cstring>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// base_object - adds a constructor and non-virtual destructor to a
|
||||
// base Python type (e.g. PyObject, PyTypeObject).
|
||||
template <class PythonType>
|
||||
struct base_object : PythonType
|
||||
{
|
||||
typedef PythonType base_python_type;
|
||||
|
||||
// Initializes type and reference count. All other fields of base_python_type are 0
|
||||
base_object(PyTypeObject* type_obj);
|
||||
|
||||
// Decrements reference count on the type
|
||||
~base_object();
|
||||
};
|
||||
|
||||
// Easy typedefs for common usage
|
||||
typedef base_object<PyObject> python_object;
|
||||
typedef base_object<PyTypeObject> python_type;
|
||||
|
||||
|
||||
//
|
||||
// base_object member function implementations
|
||||
//
|
||||
template <class PythonType>
|
||||
base_object<PythonType>::base_object(PyTypeObject* type_obj)
|
||||
{
|
||||
base_python_type* bp = this;
|
||||
#if !defined(_MSC_VER) || defined(__STLPORT)
|
||||
std::
|
||||
#endif
|
||||
memset(bp, 0, sizeof(base_python_type));
|
||||
Py_INCREF(type_obj);
|
||||
PyObject_INIT(bp, type_obj);
|
||||
}
|
||||
|
||||
template <class PythonType>
|
||||
inline base_object<PythonType>::~base_object()
|
||||
{
|
||||
Py_DECREF(ob_type);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // BASE_OBJECT_DWA051600_H_
|
||||
78
include/boost/python/detail/cast.hpp
Normal file
78
include/boost/python/detail/cast.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef CAST_DWA052500_H_
|
||||
# define CAST_DWA052500_H_
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/operators.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
inline PyTypeObject* as_base_object(const PyTypeObject*, PyObject* p)
|
||||
{
|
||||
return reinterpret_cast<PyTypeObject*>(p);
|
||||
}
|
||||
|
||||
inline PyObject* as_base_object(const PyObject*, PyObject* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
inline const PyTypeObject* as_base_object(const PyTypeObject*, const PyObject* p)
|
||||
{
|
||||
return reinterpret_cast<const PyTypeObject*>(p);
|
||||
}
|
||||
|
||||
inline const PyObject* as_base_object(const PyObject*, const PyObject* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// Convert a pointer to any type derived from PyObject or PyTypeObject to a PyObject*
|
||||
inline PyObject* as_object(PyObject* p) { return p; }
|
||||
inline PyObject* as_object(PyTypeObject* p) { return reinterpret_cast<PyObject*>(p); }
|
||||
|
||||
// If I didn't have to support stupid MSVC6 we could just use a simple template function:
|
||||
// template <class T> T* downcast(PyObject*).
|
||||
template <class T>
|
||||
struct downcast
|
||||
{
|
||||
downcast(PyObject* p)
|
||||
: m_p(static_cast<T*>(detail::as_base_object((T*)0, p)))
|
||||
{}
|
||||
|
||||
downcast(const PyObject* p)
|
||||
: m_p(static_cast<T*>(detail::as_base_object((const T*)0, p)))
|
||||
{}
|
||||
|
||||
downcast(PyTypeObject* p)
|
||||
: m_p(static_cast<T*>(p))
|
||||
{}
|
||||
|
||||
downcast(const PyTypeObject* p)
|
||||
: m_p(static_cast<T*>(p))
|
||||
{}
|
||||
|
||||
operator T*() const { return m_p; }
|
||||
|
||||
// MSVC doesn't like boost::dereferencable unless T has a default
|
||||
// constructor, so operator-> must be defined by hand :(
|
||||
T* operator->() const { return &**this; }
|
||||
|
||||
T* get() const { return m_p; }
|
||||
T& operator*() const { return *m_p; }
|
||||
private:
|
||||
T* m_p;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CAST_DWA052500_H_
|
||||
68
include/boost/python/detail/config.hpp
Normal file
68
include/boost/python/detail/config.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
// Revision History:
|
||||
// 04 Mar 01 Some fixes so it will compile with Intel C++ (Dave Abrahams)
|
||||
|
||||
#ifndef CONFIG_DWA052200_H_
|
||||
# define CONFIG_DWA052200_H_
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
// A gcc bug forces some symbols into the global namespace
|
||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
# define BOOST_PYTHON_CONVERSION
|
||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) using ::x
|
||||
# else
|
||||
# define BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE namespace boost { namespace python {
|
||||
# define BOOST_PYTHON_END_CONVERSION_NAMESPACE }} // namespace boost::python
|
||||
# define BOOST_PYTHON_CONVERSION boost::python
|
||||
# define BOOST_PYTHON_IMPORT_CONVERSION(x) void never_defined() // so we can follow the macro with a ';'
|
||||
# endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# if _MSC_VER <= 1200
|
||||
# define BOOST_MSVC6_OR_EARLIER 1
|
||||
# endif
|
||||
|
||||
# pragma warning (disable : 4786)
|
||||
|
||||
# endif
|
||||
|
||||
// Work around the broken library implementation/strict ansi checking on some
|
||||
// EDG-based compilers (e.g. alpha), which incorrectly warn that the result of
|
||||
// offsetof() is not an integer constant expression.
|
||||
# if defined(__DECCXX_VER) && __DECCXX_VER <= 60290024
|
||||
# define BOOST_OFFSETOF(s_name, s_member) \
|
||||
((size_t)__INTADDR__(&(((s_name *)0)->s_member)))
|
||||
# else
|
||||
# define BOOST_OFFSETOF(s_name, s_member) \
|
||||
offsetof(s_name, s_member)
|
||||
# endif
|
||||
|
||||
// The STLport puts all of the standard 'C' library names in std (as far as the
|
||||
// user is concerned), but without it you need a fix if you're using MSVC or
|
||||
// Intel C++
|
||||
# if defined(BOOST_MSVC_STD_ITERATOR)
|
||||
# define BOOST_CSTD_
|
||||
# else
|
||||
# define BOOST_CSTD_ std
|
||||
# endif
|
||||
|
||||
# ifndef BOOST_PYTHON_MODULE_INIT
|
||||
# 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
|
||||
# endif
|
||||
|
||||
#endif // CONFIG_DWA052200_H_
|
||||
942
include/boost/python/detail/extension_class.hpp
Normal file
942
include/boost/python/detail/extension_class.hpp
Normal file
@@ -0,0 +1,942 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file automatically generated for 10-argument constructors by
|
||||
// gen_extclass.python
|
||||
|
||||
// Revision History:
|
||||
// 17 Apr 01 Comment added with reference to cross_module.hpp (R.W. Grosse-Kunstleve)
|
||||
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
|
||||
// to_python (Dave Abrahams)
|
||||
|
||||
#ifndef EXTENSION_CLASS_DWA052000_H_
|
||||
# define EXTENSION_CLASS_DWA052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/classes.hpp>
|
||||
# include <vector>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/objects.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
# include <memory>
|
||||
# include <boost/python/detail/init_function.hpp>
|
||||
# include <typeinfo>
|
||||
# include <boost/smart_ptr.hpp>
|
||||
# include <boost/type_traits.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// forward declarations
|
||||
template <long which, class operand> struct operators;
|
||||
template <class T> struct left_operand;
|
||||
template <class T> struct right_operand;
|
||||
|
||||
enum without_downcast_t { without_downcast };
|
||||
|
||||
namespace detail {
|
||||
|
||||
// forward declarations
|
||||
class extension_instance;
|
||||
class extension_class_base;
|
||||
template <class T> class instance_holder;
|
||||
template <class T, class U> class instance_value_holder;
|
||||
template <class ref, class T> class instance_ptr_holder;
|
||||
template <class Specified> struct operand_select;
|
||||
template <long> struct choose_op;
|
||||
template <long> struct choose_rop;
|
||||
template <long> struct choose_unary_op;
|
||||
template <long> struct define_operator;
|
||||
|
||||
meta_class<extension_instance>* extension_meta_class();
|
||||
extension_instance* get_extension_instance(PyObject* p);
|
||||
void report_missing_instance_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
|
||||
void report_missing_ptr_data(extension_instance*, class_t<extension_instance>*, const std::type_info&);
|
||||
void report_missing_class_object(const std::type_info&);
|
||||
void report_released_smart_pointer(const std::type_info&);
|
||||
|
||||
template <class T>
|
||||
T* check_non_null(T* p)
|
||||
{
|
||||
if (p == 0)
|
||||
report_released_smart_pointer(typeid(T));
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class Held> class held_instance;
|
||||
|
||||
typedef void* (*conversion_function_ptr)(void*);
|
||||
|
||||
struct base_class_info
|
||||
{
|
||||
base_class_info(extension_class_base* t, conversion_function_ptr f)
|
||||
:class_object(t), convert(f)
|
||||
{}
|
||||
|
||||
extension_class_base* class_object;
|
||||
conversion_function_ptr convert;
|
||||
};
|
||||
|
||||
typedef base_class_info derived_class_info;
|
||||
|
||||
struct add_operator_base;
|
||||
|
||||
class extension_class_base : public class_t<extension_instance>
|
||||
{
|
||||
public:
|
||||
extension_class_base(const char* name);
|
||||
|
||||
public:
|
||||
// the purpose of try_class_conversions() and its related functions
|
||||
// is explained in extclass.cpp
|
||||
void* try_class_conversions(instance_holder_base*) const;
|
||||
void* try_base_class_conversions(instance_holder_base*) const;
|
||||
void* try_derived_class_conversions(instance_holder_base*) const;
|
||||
|
||||
void set_attribute(const char* name, PyObject* x);
|
||||
void set_attribute(const char* name, ref x);
|
||||
|
||||
private:
|
||||
virtual void* extract_object_from_holder(instance_holder_base* v) const = 0;
|
||||
virtual std::vector<base_class_info> const& base_classes() const = 0;
|
||||
virtual std::vector<derived_class_info> const& derived_classes() const = 0;
|
||||
|
||||
protected:
|
||||
friend struct add_operator_base;
|
||||
void add_method(reference<function> method, const char* name);
|
||||
void add_method(function* method, const char* name);
|
||||
|
||||
void add_constructor_object(function*);
|
||||
void add_setter_method(function*, const char* name);
|
||||
void add_getter_method(function*, const char* name);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class class_registry
|
||||
{
|
||||
public:
|
||||
static extension_class_base* class_object()
|
||||
{ return static_class_object; }
|
||||
|
||||
// Register/unregister the Python class object corresponding to T
|
||||
static void register_class(extension_class_base*);
|
||||
static void unregister_class(extension_class_base*);
|
||||
|
||||
// Establish C++ inheritance relationships
|
||||
static void register_base_class(base_class_info const&);
|
||||
static void register_derived_class(derived_class_info const&);
|
||||
|
||||
// Query the C++ inheritance relationships
|
||||
static std::vector<base_class_info> const& base_classes();
|
||||
static std::vector<derived_class_info> const& derived_classes();
|
||||
private:
|
||||
static extension_class_base* static_class_object;
|
||||
static std::vector<base_class_info> static_base_class_info;
|
||||
static std::vector<derived_class_info> static_derived_class_info;
|
||||
};
|
||||
|
||||
template <bool is_pointer>
|
||||
struct is_null_helper
|
||||
{
|
||||
template <class Ptr>
|
||||
static bool test(Ptr x) { return x == 0; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_null_helper<false>
|
||||
{
|
||||
template <class Ptr>
|
||||
static bool test(const Ptr& x) { return x.get() == 0; }
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
bool is_null(const Ptr& x)
|
||||
{
|
||||
return is_null_helper<(is_pointer<Ptr>::value)>::test(x);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
// This class' only job is to define from_python and to_python converters for T
|
||||
// and U. T is the class the user really intends to wrap. U is a class derived
|
||||
// from T with some virtual function overriding boilerplate, or if there are no
|
||||
// virtual functions, U = held_instance<T>.
|
||||
//
|
||||
// A look-alike of this class in root/boost/python/cross_module.hpp
|
||||
// is used for the implementation of the cross-module support
|
||||
// (export_converters and import_converters). If from_python
|
||||
// and to_python converters are added or removed from the class
|
||||
// below, the class python_import_extension_class_converters has
|
||||
// to be modified accordingly.
|
||||
//
|
||||
template <class T, class U = boost::python::detail::held_instance<T> >
|
||||
class python_extension_class_converters
|
||||
{
|
||||
public:
|
||||
// Get an object which can be used to convert T to/from python. This is used
|
||||
// as a kind of concept check by the global template
|
||||
//
|
||||
// PyObject* to_python(const T& x)
|
||||
//
|
||||
// below this class, to prevent the confusing messages that would otherwise
|
||||
// pop up. Now, if T hasn't been wrapped as an extension class, the user
|
||||
// will see an error message about the lack of an eligible
|
||||
// py_extension_class_converters() function.
|
||||
friend python_extension_class_converters py_extension_class_converters(boost::python::type<T>)
|
||||
{
|
||||
return python_extension_class_converters();
|
||||
}
|
||||
|
||||
// This is a member function because in a conforming implementation, friend
|
||||
// funcitons defined inline in the class body are all instantiated as soon
|
||||
// as the enclosing class is instantiated. If T is not copyable, that causes
|
||||
// a compiler error. Instead, we access this function through the global
|
||||
// template
|
||||
//
|
||||
// PyObject* to_python(const T& x)
|
||||
//
|
||||
// defined below this class. Since template functions are instantiated only
|
||||
// on demand, errors will be avoided unless T is noncopyable and the user
|
||||
// writes code which causes us to try to copy a T.
|
||||
PyObject* to_python(const T& x) const
|
||||
{
|
||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||
result->add_implementation(
|
||||
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
||||
new boost::python::detail::instance_value_holder<T,U>(result.get(), x)));
|
||||
return result.release();
|
||||
}
|
||||
|
||||
friend
|
||||
T* non_null_from_python(PyObject* obj, boost::python::type<T*>)
|
||||
{
|
||||
// downcast to an extension_instance, then find the actual T
|
||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
|
||||
for (iterator p = self->wrapped_objects().begin();
|
||||
p != self->wrapped_objects().end(); ++p)
|
||||
{
|
||||
boost::python::detail::instance_holder<T>* held = dynamic_cast<boost::python::detail::instance_holder<T>*>(*p);
|
||||
if (held != 0)
|
||||
return held->target();
|
||||
|
||||
// see extclass.cpp for an explanation of try_class_conversions()
|
||||
void* target = boost::python::detail::class_registry<T>::class_object()->try_class_conversions(*p);
|
||||
if(target)
|
||||
return static_cast<T*>(target);
|
||||
}
|
||||
boost::python::detail::report_missing_instance_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
|
||||
throw boost::python::argument_error();
|
||||
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Convert to T*
|
||||
friend T* from_python(PyObject* obj, boost::python::type<T*>)
|
||||
{
|
||||
if (obj == Py_None)
|
||||
return 0;
|
||||
else
|
||||
return non_null_from_python(obj, boost::python::type<T*>());
|
||||
}
|
||||
|
||||
// Extract from obj a mutable reference to the PtrType object which is holding a T.
|
||||
template <class PtrType>
|
||||
static PtrType& smart_ptr_reference(PyObject* obj, boost::python::type<PtrType>)
|
||||
{
|
||||
// downcast to an extension_instance, then find the actual T
|
||||
boost::python::detail::extension_instance* self = boost::python::detail::get_extension_instance(obj);
|
||||
typedef std::vector<boost::python::detail::instance_holder_base*>::const_iterator iterator;
|
||||
for (iterator p = self->wrapped_objects().begin();
|
||||
p != self->wrapped_objects().end(); ++p)
|
||||
{
|
||||
boost::python::detail::instance_ptr_holder<PtrType, T>* held =
|
||||
dynamic_cast<boost::python::detail::instance_ptr_holder<PtrType, T>*>(*p);
|
||||
if (held != 0)
|
||||
return held->ptr();
|
||||
}
|
||||
boost::python::detail::report_missing_ptr_data(self, boost::python::detail::class_registry<T>::class_object(), typeid(T));
|
||||
throw boost::python::argument_error();
|
||||
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
|
||||
return *(PtrType*)0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Extract from obj a reference to the PtrType object which is holding a
|
||||
// T. If it weren't for auto_ptr, it would be a constant reference. Do not
|
||||
// modify the referent except by copying an auto_ptr! If obj is None, the
|
||||
// reference denotes a default-constructed PtrType
|
||||
template <class PtrType>
|
||||
static PtrType& smart_ptr_value(PyObject* obj, boost::python::type<PtrType>)
|
||||
{
|
||||
if (obj == Py_None)
|
||||
{
|
||||
static PtrType null_ptr;
|
||||
return null_ptr;
|
||||
}
|
||||
return smart_ptr_reference(obj, boost::python::type<PtrType>());
|
||||
}
|
||||
|
||||
template <class PtrType>
|
||||
static PyObject* smart_ptr_to_python(PtrType x)
|
||||
{
|
||||
if (boost::python::detail::is_null(x))
|
||||
{
|
||||
return boost::python::detail::none();
|
||||
}
|
||||
|
||||
boost::python::reference<boost::python::detail::extension_instance> result(create_instance());
|
||||
result->add_implementation(
|
||||
std::auto_ptr<boost::python::detail::instance_holder_base>(
|
||||
new boost::python::detail::instance_ptr_holder<PtrType,T>(x)));
|
||||
return result.release();
|
||||
}
|
||||
|
||||
static boost::python::reference<boost::python::detail::extension_instance> create_instance()
|
||||
{
|
||||
PyTypeObject* class_object = boost::python::detail::class_registry<T>::class_object();
|
||||
if (class_object == 0)
|
||||
boost::python::detail::report_missing_class_object(typeid(T));
|
||||
|
||||
return boost::python::reference<boost::python::detail::extension_instance>(
|
||||
new boost::python::detail::extension_instance(class_object));
|
||||
}
|
||||
|
||||
// Convert to const T*
|
||||
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
|
||||
{ return from_python(p, boost::python::type<T*>()); }
|
||||
|
||||
// Convert to const T* const&
|
||||
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
|
||||
{ return from_python(p, boost::python::type<const T*>()); }
|
||||
|
||||
// Convert to T* const&
|
||||
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
|
||||
{ return from_python(p, boost::python::type<T*>()); }
|
||||
|
||||
// Convert to T&
|
||||
friend T& from_python(PyObject* p, boost::python::type<T&>)
|
||||
{ return *boost::python::detail::check_non_null(non_null_from_python(p, boost::python::type<T*>())); }
|
||||
|
||||
// Convert to const T&
|
||||
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
|
||||
{ return from_python(p, boost::python::type<T&>()); }
|
||||
|
||||
// Convert to T
|
||||
friend const T& from_python(PyObject* p, boost::python::type<T>)
|
||||
{ return from_python(p, boost::python::type<T&>()); }
|
||||
|
||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>)
|
||||
{ return smart_ptr_reference(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >)
|
||||
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>)
|
||||
{ return smart_ptr_value(p, boost::python::type<std::auto_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(std::auto_ptr<T> x)
|
||||
{ return smart_ptr_to_python(x); }
|
||||
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>)
|
||||
{ return smart_ptr_reference(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >)
|
||||
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>)
|
||||
{ return smart_ptr_value(p, boost::python::type<boost::shared_ptr<T> >()); }
|
||||
|
||||
friend PyObject* to_python(boost::shared_ptr<T> x)
|
||||
{ return smart_ptr_to_python(x); }
|
||||
};
|
||||
|
||||
// Convert T to_python, instantiated on demand and only if there isn't a
|
||||
// non-template overload for this function. This version is the one invoked when
|
||||
// T is a wrapped class. See the first 2 functions declared in
|
||||
// python_extension_class_converters above for more info.
|
||||
template <class T>
|
||||
PyObject* to_python(const T& x)
|
||||
{
|
||||
return py_extension_class_converters(boost::python::type<T>()).to_python(x);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
BOOST_PYTHON_IMPORT_CONVERSION(python_extension_class_converters);
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T> class instance_holder;
|
||||
|
||||
class read_only_setattr_function : public function
|
||||
{
|
||||
public:
|
||||
read_only_setattr_function(const char* name);
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
const char* description() const;
|
||||
private:
|
||||
string m_name;
|
||||
};
|
||||
|
||||
template <class From, class To>
|
||||
struct define_conversion
|
||||
{
|
||||
static void* upcast_ptr(void* v)
|
||||
{
|
||||
return static_cast<To*>(static_cast<From*>(v));
|
||||
}
|
||||
|
||||
static void* downcast_ptr(void* v)
|
||||
{
|
||||
return dynamic_cast<To*>(static_cast<From*>(v));
|
||||
}
|
||||
};
|
||||
|
||||
// An easy way to make an extension base class which wraps T. Note that Python
|
||||
// subclasses of this class will simply be class_t<extension_instance> objects.
|
||||
//
|
||||
// U should be a class derived from T which overrides virtual functions with
|
||||
// boilerplate code to call back into Python. See extclass_demo.h for examples.
|
||||
//
|
||||
// U is optional, but you won't be able to override any member functions in
|
||||
// Python which are called from C++ if you don't supply it. If you just want to
|
||||
// be able to use T in python without overriding member functions, you can omit
|
||||
// U.
|
||||
template <class T, class U = held_instance<T> >
|
||||
class extension_class
|
||||
: public python_extension_class_converters<T, U>, // This generates the to_python/from_python functions
|
||||
public extension_class_base
|
||||
{
|
||||
public:
|
||||
typedef T wrapped_type;
|
||||
typedef U callback_type;
|
||||
|
||||
// Construct with a name that comes from typeid(T).name(). The name only
|
||||
// affects the objects of this class are represented through repr()
|
||||
extension_class();
|
||||
|
||||
// Construct with the given name. The name only affects the objects of this
|
||||
// class are represented through repr()
|
||||
extension_class(const char* name);
|
||||
|
||||
~extension_class();
|
||||
|
||||
// define constructors
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
inline void def(constructor<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>)
|
||||
// The following incantation builds a signature1, signature2,... object. It
|
||||
// should _all_ get optimized away.
|
||||
{ add_constructor(
|
||||
prepend(type<A1>::id(),
|
||||
prepend(type<A2>::id(),
|
||||
prepend(type<A3>::id(),
|
||||
prepend(type<A4>::id(),
|
||||
prepend(type<A5>::id(),
|
||||
prepend(type<A6>::id(),
|
||||
prepend(type<A7>::id(),
|
||||
prepend(type<A8>::id(),
|
||||
prepend(type<A9>::id(),
|
||||
prepend(type<A10>::id(),
|
||||
signature0())))))))))));
|
||||
}
|
||||
|
||||
|
||||
// export homogeneous operators (type of both lhs and rhs is 'operator')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>());
|
||||
|
||||
// export homogeneous operators (type of both lhs and rhs is 'T const&')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>());
|
||||
template <long which, class Operand>
|
||||
inline void def(operators<which,Operand>)
|
||||
{
|
||||
typedef typename operand_select<Operand>::template wrapped<T>::type true_operand;
|
||||
def_operators(operators<which,true_operand>());
|
||||
}
|
||||
|
||||
// export heterogeneous operators (type of lhs: 'left', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||
// boost::python::right_operand<int const&>());
|
||||
|
||||
// export heterogeneous operators (type of lhs: 'T const&', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
|
||||
// boost::python::right_operand<int const&>());
|
||||
template <long which, class Left, class Right>
|
||||
inline void def(operators<which,Left>, right_operand<Right> r)
|
||||
{
|
||||
typedef typename operand_select<Left>::template wrapped<T>::type true_left;
|
||||
def_operators(operators<which,true_left>(), r);
|
||||
}
|
||||
|
||||
// export heterogeneous reverse-argument operators
|
||||
// (type of lhs: 'left', of rhs: 'right')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub), Foo>(),
|
||||
// boost::python::left_operand<int const&>());
|
||||
|
||||
// export heterogeneous reverse-argument operators
|
||||
// (type of lhs: 'left', of rhs: 'T const&')
|
||||
// usage: foo_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub)>(),
|
||||
// boost::python::left_operand<int const&>());
|
||||
template <long which, class Left, class Right>
|
||||
inline void def(operators<which,Right>, left_operand<Left> l)
|
||||
{
|
||||
typedef typename operand_select<Right>::template wrapped<T>::type true_right;
|
||||
def_operators(operators<which,true_right>(), l);
|
||||
}
|
||||
|
||||
// define a function that passes Python arguments and keywords
|
||||
// to C++ verbatim (as a 'tuple const&' and 'dictionary const&'
|
||||
// respectively). This is useful for manual argument passing.
|
||||
// It's also the only possibility to pass keyword arguments to C++.
|
||||
// Fn must have a signatur that is compatible to
|
||||
// PyObject* (*)(PyObject* aTuple, PyObject* aDictionary)
|
||||
template <class Fn>
|
||||
inline void def_raw(Fn fn, const char* name)
|
||||
{
|
||||
this->add_method(new_raw_arguments_function(fn), name);
|
||||
}
|
||||
|
||||
// define member functions. In fact this works for free functions, too -
|
||||
// they act like static member functions, or if they start with the
|
||||
// appropriate self argument (as a pointer), they can be used just like
|
||||
// ordinary member functions -- just like Python!
|
||||
template <class Fn>
|
||||
inline void def(Fn fn, const char* name)
|
||||
{
|
||||
this->add_method(new_wrapped_function(fn), name);
|
||||
}
|
||||
|
||||
// Define a virtual member function with a default implementation.
|
||||
// default_fn should be a function which provides the default implementation.
|
||||
// Be careful that default_fn does not in fact call fn virtually!
|
||||
template <class Fn, class DefaultFn>
|
||||
inline void def(Fn fn, const char* name, DefaultFn default_fn)
|
||||
{
|
||||
this->add_method(new_virtual_function(type<T>(), fn, default_fn), name);
|
||||
}
|
||||
|
||||
// Provide a function which implements x.<name>, reading from the given
|
||||
// member (pm) of the T obj
|
||||
template <class MemberType>
|
||||
inline void def_getter(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->add_getter_method(new getter_function<T, MemberType>(pm), name);
|
||||
}
|
||||
|
||||
// Provide a function which implements assignment to x.<name>, writing to
|
||||
// the given member (pm) of the T obj
|
||||
template <class MemberType>
|
||||
inline void def_setter(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->add_setter_method(new setter_function<T, MemberType>(pm), name);
|
||||
}
|
||||
|
||||
// Expose the given member (pm) of the T obj as a read-only attribute
|
||||
template <class MemberType>
|
||||
inline void def_readonly(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->add_setter_method(new read_only_setattr_function(name), name);
|
||||
this->def_getter(pm, name);
|
||||
}
|
||||
|
||||
// Expose the given member (pm) of the T obj as a read/write attribute
|
||||
template <class MemberType>
|
||||
inline void def_read_write(MemberType T::*pm, const char* name)
|
||||
{
|
||||
this->def_getter(pm, name);
|
||||
this->def_setter(pm, name);
|
||||
}
|
||||
|
||||
// define the standard coercion needed for operator overloading
|
||||
void def_standard_coerce();
|
||||
|
||||
// declare the given class a base class of this one and register
|
||||
// up and down conversion functions
|
||||
template <class S, class V>
|
||||
void declare_base(extension_class<S, V>* base)
|
||||
{
|
||||
// see extclass.cpp for an explanation of why we need to register
|
||||
// conversion functions
|
||||
base_class_info baseInfo(base,
|
||||
&define_conversion<S, T>::downcast_ptr);
|
||||
class_registry<T>::register_base_class(baseInfo);
|
||||
add_base(ref(as_object(base), ref::increment_count));
|
||||
|
||||
derived_class_info derivedInfo(this,
|
||||
&define_conversion<T, S>::upcast_ptr);
|
||||
class_registry<S>::register_derived_class(derivedInfo);
|
||||
}
|
||||
|
||||
// declare the given class a base class of this one and register
|
||||
// only up conversion function
|
||||
template <class S, class V>
|
||||
void declare_base(extension_class<S, V>* base, without_downcast_t)
|
||||
{
|
||||
// see extclass.cpp for an explanation of why we need to register
|
||||
// conversion functions
|
||||
base_class_info baseInfo(base, 0);
|
||||
class_registry<T>::register_base_class(baseInfo);
|
||||
add_base(ref(as_object(base), ref::increment_count));
|
||||
|
||||
derived_class_info derivedInfo(this,
|
||||
&define_conversion<T, S>::upcast_ptr);
|
||||
class_registry<S>::register_derived_class(derivedInfo);
|
||||
}
|
||||
|
||||
private: // types
|
||||
typedef instance_value_holder<T,U> holder;
|
||||
|
||||
private: // extension_class_base virtual function implementations
|
||||
std::vector<base_class_info> const& base_classes() const;
|
||||
std::vector<derived_class_info> const& derived_classes() const;
|
||||
void* extract_object_from_holder(instance_holder_base* v) const;
|
||||
|
||||
private: // Utility functions
|
||||
template <long which, class Operand>
|
||||
inline void def_operators(operators<which,Operand>)
|
||||
{
|
||||
def_standard_coerce();
|
||||
|
||||
// for some strange reason, this prevents MSVC from having an
|
||||
// "unrecoverable block scoping error"!
|
||||
typedef choose_op<(which & op_add)> choose_add;
|
||||
|
||||
choose_op<(which & op_add)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_sub)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_mul)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_div)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_mod)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_divmod)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_pow)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_lshift)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_rshift)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_and)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_xor)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_gt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_ne)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_invert)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_int)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_long)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_float)>::template args<Operand>::add(this);
|
||||
choose_op<(which & op_cmp)>::template args<Operand>::add(this);
|
||||
choose_unary_op<(which & op_str)>::template args<Operand>::add(this);
|
||||
}
|
||||
|
||||
template <long which, class Left, class Right>
|
||||
inline void def_operators(operators<which,Left>, right_operand<Right>)
|
||||
{
|
||||
def_standard_coerce();
|
||||
|
||||
choose_op<(which & op_add)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_sub)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_mul)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_div)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_mod)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_divmod)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_pow)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_lshift)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_rshift)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_and)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_gt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ge)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_lt)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_le)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_eq)>::template args<Left,Right>::add(this);
|
||||
choose_op<(which & op_ne)>::template args<Left,Right>::add(this);
|
||||
}
|
||||
|
||||
template <long which, class Left, class Right>
|
||||
inline void def_operators(operators<which,Right>, left_operand<Left>)
|
||||
{
|
||||
def_standard_coerce();
|
||||
|
||||
choose_rop<(which & op_add)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_sub)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_mul)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_div)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_mod)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_divmod)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_pow)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_lshift)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_rshift)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_and)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_xor)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_or)>::template args<Left,Right>::add(this);
|
||||
choose_rop<(which & op_cmp)>::template args<Left,Right>::add(this);
|
||||
}
|
||||
|
||||
template <class signature>
|
||||
void add_constructor(signature sig)
|
||||
{
|
||||
this->add_constructor_object(init_function<holder>::create(sig));
|
||||
}
|
||||
};
|
||||
|
||||
// A simple wrapper over a T which allows us to use extension_class<T> with a
|
||||
// single template parameter only. See extension_class<T>, above.
|
||||
template <class Held>
|
||||
class held_instance : public Held
|
||||
{
|
||||
// There are no member functions: we want to avoid inadvertently overriding
|
||||
// any virtual functions in Held.
|
||||
public:
|
||||
held_instance(PyObject*) : Held() {}
|
||||
template <class A1>
|
||||
held_instance(PyObject*, A1 a1) : Held(a1) {}
|
||||
template <class A1, class A2>
|
||||
held_instance(PyObject*, A1 a1, A2 a2) : Held(a1, a2) {}
|
||||
template <class A1, class A2, class A3>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3) : Held(a1, a2, a3) {}
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4) : Held(a1, a2, a3, a4) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : Held(a1, a2, a3, a4, a5) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : Held(a1, a2, a3, a4, a5, a6) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : 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>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : 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>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : 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>
|
||||
held_instance(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : Held(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
};
|
||||
|
||||
// Abstract base class for all obj holders. Base for template class
|
||||
// instance_holder<>, below.
|
||||
class instance_holder_base
|
||||
{
|
||||
public:
|
||||
virtual ~instance_holder_base() {}
|
||||
virtual bool held_by_value() = 0;
|
||||
};
|
||||
|
||||
// Abstract base class which holds a Held, somehow. Provides a uniform way to
|
||||
// get a pointer to the held object
|
||||
template <class Held>
|
||||
class instance_holder : public instance_holder_base
|
||||
{
|
||||
public:
|
||||
virtual Held*target() = 0;
|
||||
};
|
||||
|
||||
// Concrete class which holds a Held by way of a wrapper class Wrapper. If Held
|
||||
// can be constructed with arguments (A1...An), Wrapper must have a
|
||||
// corresponding constructor for arguments (PyObject*, A1...An). Wrapper is
|
||||
// neccessary to implement virtual function callbacks (there must be a
|
||||
// back-pointer to the actual Python object so that we can call any
|
||||
// overrides). held_instance (above) is used as a default Wrapper class when
|
||||
// there are no virtual functions.
|
||||
template <class Held, class Wrapper>
|
||||
class instance_value_holder : public instance_holder<Held>
|
||||
{
|
||||
public:
|
||||
Held* target() { return &m_held; }
|
||||
Wrapper* value_target() { return &m_held; }
|
||||
|
||||
instance_value_holder(extension_instance* p) :
|
||||
m_held(p) {}
|
||||
template <class A1>
|
||||
instance_value_holder(extension_instance* p, A1 a1) :
|
||||
m_held(p, a1) {}
|
||||
template <class A1, class A2>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2) :
|
||||
m_held(p, a1, a2) {}
|
||||
template <class A1, class A2, class A3>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3) :
|
||||
m_held(p, a1, a2, a3) {}
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4) :
|
||||
m_held(p, a1, a2, a3, a4) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) :
|
||||
m_held(p, a1, a2, a3, a4, a5) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7) {}
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) :
|
||||
m_held(p, 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>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) :
|
||||
m_held(p, 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>
|
||||
instance_value_holder(extension_instance* p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) :
|
||||
m_held(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
|
||||
public: // implementation of instance_holder_base required interface
|
||||
bool held_by_value() { return true; }
|
||||
|
||||
private:
|
||||
Wrapper m_held;
|
||||
};
|
||||
|
||||
// Concrete class which holds a HeldType by way of a (possibly smart) pointer
|
||||
// PtrType. By default, these are only generated for PtrType ==
|
||||
// std::auto_ptr<HeldType> and PtrType == boost::shared_ptr<HeldType>.
|
||||
template <class PtrType, class HeldType>
|
||||
class instance_ptr_holder : public instance_holder<HeldType>
|
||||
{
|
||||
public:
|
||||
HeldType* target() { return &*m_ptr; }
|
||||
PtrType& ptr() { return m_ptr; }
|
||||
|
||||
instance_ptr_holder(PtrType ptr) : m_ptr(ptr) {}
|
||||
|
||||
public: // implementation of instance_holder_base required interface
|
||||
bool held_by_value() { return false; }
|
||||
private:
|
||||
PtrType m_ptr;
|
||||
};
|
||||
|
||||
class extension_instance : public instance
|
||||
{
|
||||
public:
|
||||
extension_instance(PyTypeObject* class_);
|
||||
~extension_instance();
|
||||
|
||||
void add_implementation(std::auto_ptr<instance_holder_base> holder);
|
||||
|
||||
typedef std::vector<instance_holder_base*> held_objects;
|
||||
const held_objects& wrapped_objects() const
|
||||
{ return m_wrapped_objects; }
|
||||
private:
|
||||
held_objects m_wrapped_objects;
|
||||
};
|
||||
|
||||
//
|
||||
// Template function implementations
|
||||
//
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::extension_class()
|
||||
: extension_class_base(typeid(T).name())
|
||||
{
|
||||
class_registry<T>::register_class(this);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::extension_class(const char* name)
|
||||
: extension_class_base(name)
|
||||
{
|
||||
class_registry<T>::register_class(this);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void extension_class<T, U>::def_standard_coerce()
|
||||
{
|
||||
ref coerce_fct = dict().get_item(string("__coerce__"));
|
||||
|
||||
if(coerce_fct.get() == 0) // not yet defined
|
||||
this->def(&standard_coerce, "__coerce__");
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
std::vector<base_class_info> const&
|
||||
extension_class<T, U>::base_classes() const
|
||||
{
|
||||
return class_registry<T>::base_classes();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
std::vector<derived_class_info> const&
|
||||
extension_class<T, U>::derived_classes() const
|
||||
{
|
||||
return class_registry<T>::derived_classes();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void* extension_class<T, U>::extract_object_from_holder(instance_holder_base* v) const
|
||||
{
|
||||
instance_holder<T>* held = dynamic_cast<instance_holder<T>*>(v);
|
||||
if(held)
|
||||
return held->target();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
extension_class<T, U>::~extension_class()
|
||||
{
|
||||
class_registry<T>::unregister_class(this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void class_registry<T>::register_class(extension_class_base* p)
|
||||
{
|
||||
// You're not expected to create more than one of these!
|
||||
assert(static_class_object == 0);
|
||||
static_class_object = p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void class_registry<T>::unregister_class(extension_class_base* p)
|
||||
{
|
||||
// The user should be destroying the same object they created.
|
||||
assert(static_class_object == p);
|
||||
(void)p; // unused in shipping version
|
||||
static_class_object = 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void class_registry<T>::register_base_class(base_class_info const& i)
|
||||
{
|
||||
static_base_class_info.push_back(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void class_registry<T>::register_derived_class(derived_class_info const& i)
|
||||
{
|
||||
static_derived_class_info.push_back(i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::vector<base_class_info> const& class_registry<T>::base_classes()
|
||||
{
|
||||
return static_base_class_info;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::vector<derived_class_info> const& class_registry<T>::derived_classes()
|
||||
{
|
||||
return static_derived_class_info;
|
||||
}
|
||||
|
||||
//
|
||||
// Static data member declaration.
|
||||
//
|
||||
template <class T>
|
||||
extension_class_base* class_registry<T>::static_class_object;
|
||||
template <class T>
|
||||
std::vector<base_class_info> class_registry<T>::static_base_class_info;
|
||||
template <class T>
|
||||
std::vector<derived_class_info> class_registry<T>::static_derived_class_info;
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // EXTENSION_CLASS_DWA052000_H_
|
||||
311
include/boost/python/detail/functions.hpp
Normal file
311
include/boost/python/detail/functions.hpp
Normal file
@@ -0,0 +1,311 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef FUNCTIONS_DWA051400_H_
|
||||
# define FUNCTIONS_DWA051400_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <boost/python/caller.hpp>
|
||||
# include <boost/call_traits.hpp>
|
||||
# include <boost/python/objects.hpp>
|
||||
# include <boost/python/detail/base_object.hpp>
|
||||
# include <typeinfo>
|
||||
# include <vector>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
// forward declaration
|
||||
class extension_instance;
|
||||
|
||||
|
||||
// function --
|
||||
// the common base class for all overloadable function and method objects
|
||||
// supplied by the library.
|
||||
class function : public python_object
|
||||
{
|
||||
public:
|
||||
function();
|
||||
// function objects are reasonably rare, so we guess we can afford a virtual table.
|
||||
// This cuts down on the number of distinct type objects which need to be defined.
|
||||
virtual ~function() {}
|
||||
|
||||
PyObject* call(PyObject* args, PyObject* keywords) const;
|
||||
static void add_to_namespace(reference<function> f, const char* name, PyObject* dict);
|
||||
|
||||
private:
|
||||
virtual PyObject* do_call(PyObject* args, PyObject* keywords) const = 0;
|
||||
virtual const char* description() const = 0;
|
||||
private:
|
||||
struct type_object;
|
||||
private:
|
||||
reference<function> m_overloads; // A linked list of the function overloads
|
||||
};
|
||||
|
||||
// wrapped_function_pointer<> --
|
||||
// A single function or member function pointer wrapped and presented to
|
||||
// Python as a callable object.
|
||||
//
|
||||
// Template parameters:
|
||||
// R - the return type of the function pointer
|
||||
// F - the complete type of the wrapped function pointer
|
||||
template <class R, class F>
|
||||
struct wrapped_function_pointer : function
|
||||
{
|
||||
typedef F ptr_fun; // pointer-to--function or pointer-to-member-function
|
||||
|
||||
wrapped_function_pointer(ptr_fun pf)
|
||||
: m_pf(pf) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// This is where the boundary between the uniform Python function
|
||||
// interface and the statically-checked C++ function interface is
|
||||
// crossed.
|
||||
return caller<R>::call(m_pf, args, keywords);
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(F).name(); }
|
||||
|
||||
private:
|
||||
const ptr_fun m_pf;
|
||||
};
|
||||
|
||||
// raw_arguments_function
|
||||
// A function that passes the Python argument tuple and keyword dictionary
|
||||
// verbatim to C++ (useful for customized argument parsing and variable
|
||||
// argument lists)
|
||||
template <class Ret, class Args, class Keywords>
|
||||
struct raw_arguments_function : function
|
||||
{
|
||||
typedef Ret (*ptr_fun)(Args, Keywords);
|
||||
|
||||
raw_arguments_function(ptr_fun pf)
|
||||
: m_pf(pf) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
ref dict(keywords ?
|
||||
ref(keywords, ref::increment_count) :
|
||||
ref(PyDict_New()));
|
||||
|
||||
return to_python(
|
||||
(*m_pf)(from_python(args, boost::python::type<Args>()),
|
||||
from_python(dict.get(), boost::python::type<Keywords>())));
|
||||
}
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(ptr_fun).name(); }
|
||||
|
||||
private:
|
||||
const ptr_fun m_pf;
|
||||
};
|
||||
|
||||
// virtual_function<> --
|
||||
// A virtual function with a default implementation wrapped and presented
|
||||
// to Python as a callable object.
|
||||
//
|
||||
// Template parameters:
|
||||
// T - the type of the target class
|
||||
// R - the return type of the function pointer
|
||||
// V - the virtual function pointer being wrapped
|
||||
// (should be of the form R(T::*)(<args>), or R (*)(T, <args>))
|
||||
// D - a function which takes a T&, const T&, T*, or const T* first
|
||||
// parameter and calls T::f on it /non-virtually/, where V
|
||||
// approximates &T::f.
|
||||
template <class T, class R, class V, class D>
|
||||
class virtual_function : public function
|
||||
{
|
||||
public:
|
||||
virtual_function(V virtual_function_ptr, D default_implementation)
|
||||
: m_virtual_function_ptr(virtual_function_ptr),
|
||||
m_default_implementation(default_implementation)
|
||||
{}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(V).name(); }
|
||||
|
||||
private:
|
||||
const V m_virtual_function_ptr;
|
||||
const D m_default_implementation;
|
||||
};
|
||||
|
||||
// A helper function for new_member_function(), below. Implements the core
|
||||
// functionality once the return type has already been deduced. R is expected to
|
||||
// be type<X>, where X is the actual return type of pmf.
|
||||
template <class F, class R>
|
||||
function* new_wrapped_function_aux(R, F pmf)
|
||||
{
|
||||
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
|
||||
typedef typename R::type return_type;
|
||||
return new wrapped_function_pointer<return_type, F>(pmf);
|
||||
}
|
||||
|
||||
// Create and return a new member function object wrapping the given
|
||||
// pointer-to-member function
|
||||
template <class F>
|
||||
inline function* new_wrapped_function(F pmf)
|
||||
{
|
||||
// Deduce the return type and pass it off to the helper function above
|
||||
return new_wrapped_function_aux(return_value(pmf), pmf);
|
||||
}
|
||||
|
||||
template <class R, class Args, class keywords>
|
||||
function* new_raw_arguments_function(R (*pmf)(Args, keywords))
|
||||
{
|
||||
return new raw_arguments_function<R, Args, keywords>(pmf);
|
||||
}
|
||||
|
||||
|
||||
// A helper function for new_virtual_function(), below. Implements the core
|
||||
// functionality once the return type has already been deduced. R is expected to
|
||||
// be type<X>, where X is the actual return type of V.
|
||||
template <class T, class R, class V, class D>
|
||||
inline function* new_virtual_function_aux(
|
||||
type<T>, R, V virtual_function_ptr, D default_implementation
|
||||
)
|
||||
{
|
||||
// We can't just use "typename R::Type" below because MSVC (incorrectly) pukes.
|
||||
typedef typename R::type return_type;
|
||||
return new virtual_function<T, return_type, V, D>(
|
||||
virtual_function_ptr, default_implementation);
|
||||
}
|
||||
|
||||
// Create and return a new virtual_function object wrapping the given
|
||||
// virtual_function_ptr and default_implementation
|
||||
template <class T, class V, class D>
|
||||
inline function* new_virtual_function(
|
||||
type<T>, V virtual_function_ptr, D default_implementation
|
||||
)
|
||||
{
|
||||
// Deduce the return type and pass it off to the helper function above
|
||||
return new_virtual_function_aux(
|
||||
type<T>(), return_value(virtual_function_ptr),
|
||||
virtual_function_ptr, default_implementation);
|
||||
}
|
||||
|
||||
// A function with a bundled "bound target" object. This is what is produced by
|
||||
// the expression a.b where a is an instance or extension_instance object and b
|
||||
// is a callable object not found in the obj namespace but on its class or
|
||||
// a base class.
|
||||
class bound_function : public python_object
|
||||
{
|
||||
public:
|
||||
static bound_function* create(const ref& target, const ref& fn);
|
||||
|
||||
bound_function(const ref& target, const ref& fn);
|
||||
PyObject* call(PyObject*args, PyObject* keywords) const;
|
||||
PyObject* getattr(const char* name) const;
|
||||
|
||||
private:
|
||||
struct type_object;
|
||||
friend struct type_object;
|
||||
|
||||
ref m_target;
|
||||
ref m_unbound_function;
|
||||
|
||||
private: // data members for allocation/deallocation optimization
|
||||
bound_function* m_free_list_link;
|
||||
|
||||
static bound_function* free_list;
|
||||
};
|
||||
|
||||
// Special functions designed to access data members of a wrapped C++ object.
|
||||
template <class ClassType, class MemberType>
|
||||
class getter_function : public function
|
||||
{
|
||||
public:
|
||||
typedef MemberType ClassType::* pointer_to_member;
|
||||
|
||||
getter_function(pointer_to_member pm)
|
||||
: m_pm(pm) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(MemberType (*)(const ClassType&)).name(); }
|
||||
private:
|
||||
pointer_to_member m_pm;
|
||||
};
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
class setter_function : public function
|
||||
{
|
||||
public:
|
||||
typedef MemberType ClassType::* pointer_to_member;
|
||||
|
||||
setter_function(pointer_to_member pm)
|
||||
: m_pm(pm) {}
|
||||
|
||||
private:
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(const ClassType&, const MemberType&)).name(); }
|
||||
private:
|
||||
pointer_to_member m_pm;
|
||||
};
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
PyObject* getter_function<ClassType, MemberType>::do_call(
|
||||
PyObject* args, PyObject* /* keywords */) const
|
||||
{
|
||||
PyObject* self;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
||||
return 0;
|
||||
|
||||
return to_python(
|
||||
from_python(self, type<const ClassType*>())->*m_pm);
|
||||
}
|
||||
|
||||
template <class ClassType, class MemberType>
|
||||
PyObject* setter_function<ClassType, MemberType>::do_call(
|
||||
PyObject* args, PyObject* /* keywords */) const
|
||||
{
|
||||
PyObject* self;
|
||||
PyObject* value;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &self, &value))
|
||||
return 0;
|
||||
|
||||
typedef typename boost::call_traits<MemberType>::const_reference extract_type;
|
||||
from_python(self, type<ClassType*>())->*m_pm
|
||||
= from_python(value, type<extract_type>());
|
||||
|
||||
return none();
|
||||
}
|
||||
|
||||
template <class T, class R, class V, class D>
|
||||
PyObject* virtual_function<T,R,V,D>::do_call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// If the target object is held by pointer, we must call through the virtual
|
||||
// function pointer to the most-derived override.
|
||||
PyObject* target = PyTuple_GetItem(args, 0);
|
||||
if (target != 0)
|
||||
{
|
||||
extension_instance* self = get_extension_instance(target);
|
||||
if (self->wrapped_objects().size() == 1
|
||||
&& !self->wrapped_objects()[0]->held_by_value())
|
||||
{
|
||||
return caller<R>::call(m_virtual_function_ptr, args, keywords);
|
||||
}
|
||||
}
|
||||
return caller<R>::call(m_default_implementation, args, keywords);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // FUNCTIONS_DWA051400_H_
|
||||
508
include/boost/python/detail/init_function.hpp
Normal file
508
include/boost/python/detail/init_function.hpp
Normal file
@@ -0,0 +1,508 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file was generated for %d-argument constructors by gen_init_function.python
|
||||
|
||||
#ifndef INIT_FUNCTION_DWA052000_H_
|
||||
# define INIT_FUNCTION_DWA052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/functions.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <typeinfo>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// parameter_traits - so far, this is a way to pass a const T& when we can be
|
||||
// sure T is not a reference type, and a raw T otherwise. This should be
|
||||
// rolled into boost::call_traits. Ordinarily, parameter_traits would be
|
||||
// written:
|
||||
//
|
||||
// template <class T> struct parameter_traits
|
||||
// {
|
||||
// typedef const T& const_reference;
|
||||
// };
|
||||
//
|
||||
// template <class T> struct parameter_traits<T&>
|
||||
// {
|
||||
// typedef T& const_reference;
|
||||
// };
|
||||
//
|
||||
// template <> struct parameter_traits<void>
|
||||
// {
|
||||
// typedef void const_reference;
|
||||
// };
|
||||
//
|
||||
// ...but since we can't partially specialize on reference types, we need this
|
||||
// long-winded but equivalent incantation.
|
||||
|
||||
// const_ref_selector -- an implementation detail of parameter_traits (below). This uses
|
||||
// the usual "poor man's partial specialization" hack for MSVC.
|
||||
template <bool is_ref>
|
||||
struct const_ref_selector
|
||||
{
|
||||
template <class T>
|
||||
struct const_ref
|
||||
{
|
||||
typedef const T& type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct const_ref_selector<true>
|
||||
{
|
||||
template <class T>
|
||||
struct const_ref
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4181)
|
||||
# endif // BOOST_MSVC
|
||||
template <class T>
|
||||
struct parameter_traits
|
||||
{
|
||||
private:
|
||||
enum { is_ref = boost::is_reference<T>::value };
|
||||
typedef const_ref_selector<is_ref> selector;
|
||||
public:
|
||||
typedef typename selector::template const_ref<T>::type const_reference;
|
||||
};
|
||||
# ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
# endif // BOOST_MSVC
|
||||
|
||||
// Full spcialization for void
|
||||
template <>
|
||||
struct parameter_traits<void>
|
||||
{
|
||||
typedef void const_reference;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class reference_parameter
|
||||
{
|
||||
typedef typename parameter_traits<T>::const_reference const_reference;
|
||||
public:
|
||||
reference_parameter(const_reference value)
|
||||
: value(value) {}
|
||||
operator const_reference() { return value; }
|
||||
private:
|
||||
const_reference value;
|
||||
};
|
||||
|
||||
class extension_instance;
|
||||
class instance_holder_base;
|
||||
|
||||
class init;
|
||||
template <class T> struct init0;
|
||||
template <class T, class A1> struct init1;
|
||||
template <class T, class A1, class A2> struct init2;
|
||||
template <class T, class A1, class A2, class A3> struct init3;
|
||||
template <class T, class A1, class A2, class A3, class A4> struct init4;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5> struct init5;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6> struct init6;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct init7;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct init8;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct init9;
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> struct init10;
|
||||
|
||||
template <class T>
|
||||
struct init_function
|
||||
{
|
||||
static init* create(signature0) {
|
||||
return new init0<T>;
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
static init* create(signature1<A1>) {
|
||||
return new init1<T,
|
||||
detail::parameter_traits<A1>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
static init* create(signature2<A1, A2>) {
|
||||
return new init2<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
static init* create(signature3<A1, A2, A3>) {
|
||||
return new init3<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
static init* create(signature4<A1, A2, A3, A4>) {
|
||||
return new init4<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
static init* create(signature5<A1, A2, A3, A4, A5>) {
|
||||
return new init5<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
static init* create(signature6<A1, A2, A3, A4, A5, A6>) {
|
||||
return new init6<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
static init* create(signature7<A1, A2, A3, A4, A5, A6, A7>) {
|
||||
return new init7<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
static init* create(signature8<A1, A2, A3, A4, A5, A6, A7, A8>) {
|
||||
return new init8<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
static init* create(signature9<A1, A2, A3, A4, A5, A6, A7, A8, A9>) {
|
||||
return new init9<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference,
|
||||
detail::parameter_traits<A9>::const_reference>;
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
static init* create(signature10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>) {
|
||||
return new init10<T,
|
||||
detail::parameter_traits<A1>::const_reference,
|
||||
detail::parameter_traits<A2>::const_reference,
|
||||
detail::parameter_traits<A3>::const_reference,
|
||||
detail::parameter_traits<A4>::const_reference,
|
||||
detail::parameter_traits<A5>::const_reference,
|
||||
detail::parameter_traits<A6>::const_reference,
|
||||
detail::parameter_traits<A7>::const_reference,
|
||||
detail::parameter_traits<A8>::const_reference,
|
||||
detail::parameter_traits<A9>::const_reference,
|
||||
detail::parameter_traits<A10>::const_reference>;
|
||||
}
|
||||
};
|
||||
|
||||
class init : public function
|
||||
{
|
||||
private: // override function hook
|
||||
PyObject* do_call(PyObject* args, PyObject* keywords) const;
|
||||
private:
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct init0 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("")))
|
||||
throw argument_error();
|
||||
return new T(self
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1>
|
||||
struct init1 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &a1))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2>
|
||||
struct init2 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OO"), &a1, &a2))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3>
|
||||
struct init3 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOO"), &a1, &a2, &a3))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4>
|
||||
struct init4 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOO"), &a1, &a2, &a3, &a4))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5>
|
||||
struct init5 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOO"), &a1, &a2, &a3, &a4, &a5))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct init6 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
struct init7 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
struct init8 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
struct init9 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
PyObject* a9;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
|
||||
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9)).name(); }
|
||||
};
|
||||
|
||||
template <class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
struct init10 : init
|
||||
{
|
||||
virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
PyObject* a4;
|
||||
PyObject* a5;
|
||||
PyObject* a6;
|
||||
PyObject* a7;
|
||||
PyObject* a8;
|
||||
PyObject* a9;
|
||||
PyObject* a10;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10))
|
||||
throw argument_error();
|
||||
return new T(self,
|
||||
boost::python::detail::reference_parameter<A1>(from_python(a1, type<A1>())),
|
||||
boost::python::detail::reference_parameter<A2>(from_python(a2, type<A2>())),
|
||||
boost::python::detail::reference_parameter<A3>(from_python(a3, type<A3>())),
|
||||
boost::python::detail::reference_parameter<A4>(from_python(a4, type<A4>())),
|
||||
boost::python::detail::reference_parameter<A5>(from_python(a5, type<A5>())),
|
||||
boost::python::detail::reference_parameter<A6>(from_python(a6, type<A6>())),
|
||||
boost::python::detail::reference_parameter<A7>(from_python(a7, type<A7>())),
|
||||
boost::python::detail::reference_parameter<A8>(from_python(a8, type<A8>())),
|
||||
boost::python::detail::reference_parameter<A9>(from_python(a9, type<A9>())),
|
||||
boost::python::detail::reference_parameter<A10>(from_python(a10, type<A10>()))
|
||||
);
|
||||
}
|
||||
const char* description() const
|
||||
{ return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)).name(); }
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // INIT_FUNCTION_DWA052000_H_
|
||||
21
include/boost/python/detail/none.hpp
Normal file
21
include/boost/python/detail/none.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef NONE_DWA_052000_H_
|
||||
# define NONE_DWA_052000_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
inline PyObject* none() { Py_INCREF(Py_None); return Py_None; }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // NONE_DWA_052000_H_
|
||||
251
include/boost/python/detail/signatures.hpp
Normal file
251
include/boost/python/detail/signatures.hpp
Normal file
@@ -0,0 +1,251 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// This file automatically generated by gen_signatures.python for 10 arguments.
|
||||
#ifndef SIGNATURES_DWA050900_H_
|
||||
# define SIGNATURES_DWA050900_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail {
|
||||
// A stand-in for the built-in void. This one can be passed to functions and
|
||||
// (under MSVC, which has a bug, be used as a default template type parameter).
|
||||
struct void_t {};
|
||||
}
|
||||
|
||||
// An envelope in which type information can be delivered for the purposes
|
||||
// of selecting an overloaded from_python() function. This is needed to work
|
||||
// around MSVC's lack of partial specialiation/ordering. Where normally we'd
|
||||
// want to form a function call like void f<const T&>(), We instead pass
|
||||
// type<const T&> as one of the function parameters to select a particular
|
||||
// overload.
|
||||
//
|
||||
// The id typedef helps us deal with the lack of partial ordering by generating
|
||||
// unique types for constructor signatures. In general, type<T>::id is type<T>,
|
||||
// but type<void_t>::id is just void_t.
|
||||
template <class T>
|
||||
struct type
|
||||
{
|
||||
typedef type id;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct type<boost::python::detail::void_t>
|
||||
{
|
||||
typedef boost::python::detail::void_t id;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// These basically encapsulate a chain of types, , used to make the syntax of
|
||||
// add(constructor<T1, ...>()) work. We need to produce a unique type for each number
|
||||
// of non-default parameters to constructor<>. Q: why not use a recursive
|
||||
// formulation for infinite extensibility? A: MSVC6 seems to choke on constructs
|
||||
// that involve recursive template nesting.
|
||||
//
|
||||
// signature chaining
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
|
||||
struct signature10 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
|
||||
struct signature9 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class X>
|
||||
inline signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9> prepend(type<X>, signature9<T1, T2, T3, T4, T5, T6, T7, T8, T9>)
|
||||
{ return signature10<X, T1, T2, T3, T4, T5, T6, T7, T8, T9>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
struct signature8 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class X>
|
||||
inline signature9<X, T1, T2, T3, T4, T5, T6, T7, T8> prepend(type<X>, signature8<T1, T2, T3, T4, T5, T6, T7, T8>)
|
||||
{ return signature9<X, T1, T2, T3, T4, T5, T6, T7, T8>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
struct signature7 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class X>
|
||||
inline signature8<X, T1, T2, T3, T4, T5, T6, T7> prepend(type<X>, signature7<T1, T2, T3, T4, T5, T6, T7>)
|
||||
{ return signature8<X, T1, T2, T3, T4, T5, T6, T7>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
struct signature6 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class X>
|
||||
inline signature7<X, T1, T2, T3, T4, T5, T6> prepend(type<X>, signature6<T1, T2, T3, T4, T5, T6>)
|
||||
{ return signature7<X, T1, T2, T3, T4, T5, T6>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
struct signature5 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class X>
|
||||
inline signature6<X, T1, T2, T3, T4, T5> prepend(type<X>, signature5<T1, T2, T3, T4, T5>)
|
||||
{ return signature6<X, T1, T2, T3, T4, T5>(); }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
struct signature4 {};
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class X>
|
||||
inline signature5<X, T1, T2, T3, T4> prepend(type<X>, signature4<T1, T2, T3, T4>)
|
||||
{ return signature5<X, T1, T2, T3, T4>(); }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct signature3 {};
|
||||
|
||||
template <class T1, class T2, class T3, class X>
|
||||
inline signature4<X, T1, T2, T3> prepend(type<X>, signature3<T1, T2, T3>)
|
||||
{ return signature4<X, T1, T2, T3>(); }
|
||||
|
||||
template <class T1, class T2>
|
||||
struct signature2 {};
|
||||
|
||||
template <class T1, class T2, class X>
|
||||
inline signature3<X, T1, T2> prepend(type<X>, signature2<T1, T2>)
|
||||
{ return signature3<X, T1, T2>(); }
|
||||
|
||||
template <class T1>
|
||||
struct signature1 {};
|
||||
|
||||
template <class T1, class X>
|
||||
inline signature2<X, T1> prepend(type<X>, signature1<T1>)
|
||||
{ return signature2<X, T1>(); }
|
||||
|
||||
struct signature0 {};
|
||||
|
||||
template <class X>
|
||||
inline signature1<X> prepend(type<X>, signature0)
|
||||
{ return signature1<X>(); }
|
||||
|
||||
|
||||
// This one terminates the chain. Prepending void_t to the head of a void_t
|
||||
// signature results in a void_t signature again.
|
||||
inline signature0 prepend(void_t, signature0) { return signature0(); }
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class A1 = detail::void_t, class A2 = detail::void_t, class A3 = detail::void_t, class A4 = detail::void_t, class A5 = detail::void_t, class A6 = detail::void_t, class A7 = detail::void_t, class A8 = detail::void_t, class A9 = detail::void_t, class A10 = detail::void_t>
|
||||
struct constructor
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// Return value extraction:
|
||||
|
||||
// This is just another little envelope for carrying a typedef (see type,
|
||||
// above). I could have re-used type, but that has a very specific purpose. I
|
||||
// thought this would be clearer.
|
||||
template <class T>
|
||||
struct return_value_select { typedef T type; };
|
||||
|
||||
// free functions
|
||||
template <class R>
|
||||
return_value_select<R> return_value(R (*)()) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1>
|
||||
return_value_select<R> return_value(R (*)(A1)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2>
|
||||
return_value_select<R> return_value(R (*)(A1, A2)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
|
||||
|
||||
// TODO(?): handle 'const void'
|
||||
|
||||
// member functions
|
||||
template <class R, class T>
|
||||
return_value_select<R> return_value(R (T::*)()) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1>
|
||||
return_value_select<R> return_value(R (T::*)(A1)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T>
|
||||
return_value_select<R> return_value(R (T::*)() const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1>
|
||||
return_value_select<R> return_value(R (T::*)(A1) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { return return_value_select<R>(); }
|
||||
|
||||
template <class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
|
||||
return_value_select<R> return_value(R (T::*)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { return return_value_select<R>(); }
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif
|
||||
68
include/boost/python/detail/singleton.hpp
Normal file
68
include/boost/python/detail/singleton.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef SINGLETON_DWA051900_H_
|
||||
# define SINGLETON_DWA051900_H_
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
struct empty {};
|
||||
template <class Derived, class Base = empty>
|
||||
struct singleton : Base
|
||||
{
|
||||
typedef singleton singleton_base; // Convenience type for derived class constructors
|
||||
|
||||
static Derived* instance();
|
||||
|
||||
// Pass-through constructors
|
||||
singleton() : Base() {}
|
||||
|
||||
template <class A1>
|
||||
singleton(const A1& a1) : Base(a1) {}
|
||||
|
||||
template <class A1, class A2>
|
||||
singleton(const A1& a1, const A2& a2) : Base(a1, a2) {}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3) : Base(a1, a2, a3) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4) : Base(a1, a2, a3, a4) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) : Base(a1, a2, a3, a4, a5) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) : Base(a1, a2, a3, a4, a5, a6) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) : Base(a1, a2, a3, a4, a5, a6, a7) {}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) : Base(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>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9) : Base(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>
|
||||
singleton(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) : Base(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {}
|
||||
|
||||
};
|
||||
|
||||
template <class Derived, class Base>
|
||||
Derived* singleton<Derived,Base>::instance()
|
||||
{
|
||||
static Derived x;
|
||||
return &x;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif
|
||||
417
include/boost/python/detail/types.hpp
Normal file
417
include/boost/python/detail/types.hpp
Normal file
@@ -0,0 +1,417 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#ifndef TYPES_DWA051800_H_
|
||||
# define TYPES_DWA051800_H_
|
||||
|
||||
// Usage:
|
||||
// class X : public
|
||||
// boost::python::callable<
|
||||
// boost::python::getattrable <
|
||||
// boost::python::setattrable<python_object, X> > >
|
||||
// {
|
||||
// public:
|
||||
// ref call(args, kw);
|
||||
// ref getattr(args, kw);
|
||||
// ref setattr(args, kw);
|
||||
// };
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/signatures.hpp> // really just for type<>
|
||||
# include <boost/python/detail/cast.hpp>
|
||||
# include <boost/python/detail/base_object.hpp>
|
||||
# include <typeinfo>
|
||||
# include <vector>
|
||||
# include <cassert>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
class string;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class instance_holder_base;
|
||||
|
||||
class type_object_base : public python_type
|
||||
{
|
||||
public:
|
||||
explicit type_object_base(PyTypeObject* type_type);
|
||||
virtual ~type_object_base();
|
||||
|
||||
public:
|
||||
enum capability {
|
||||
hash, call, str, getattr, setattr, compare, repr, richcompare,
|
||||
|
||||
mapping_length, mapping_subscript, mapping_ass_subscript,
|
||||
|
||||
sequence_length, sequence_item, sequence_ass_item,
|
||||
sequence_concat, sequence_repeat, sequence_slice, sequence_ass_slice,
|
||||
|
||||
number_add, number_subtract, number_multiply, number_divide,
|
||||
number_remainder, number_divmod, number_power, number_negative,
|
||||
number_positive, number_absolute, number_nonzero, number_invert,
|
||||
number_lshift, number_rshift, number_and, number_xor, number_or,
|
||||
number_coerce, number_int, number_long, number_float, number_oct,
|
||||
number_hex, number_inplace_add, number_inplace_subtract,
|
||||
number_inplace_multiply, number_inplace_divide,
|
||||
number_inplace_remainder, number_inplace_power,
|
||||
number_inplace_lshift, number_inplace_rshift,
|
||||
number_inplace_and, number_inplace_or, number_inplace_xor
|
||||
};
|
||||
|
||||
void enable(capability);
|
||||
|
||||
//
|
||||
// type behaviors
|
||||
//
|
||||
public: // Callbacks for basic type functionality.
|
||||
virtual PyObject* instance_repr(PyObject*) const;
|
||||
virtual int instance_compare(PyObject*, PyObject* other) const;
|
||||
virtual PyObject* instance_str(PyObject*) const;
|
||||
virtual long instance_hash(PyObject*) const;
|
||||
virtual PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
|
||||
virtual PyObject* instance_getattr(PyObject* obj, const char* name) const;
|
||||
virtual int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
|
||||
|
||||
// Dealloc is a special case, since every type needs a nonzero tp_dealloc slot.
|
||||
virtual void instance_dealloc(PyObject*) const = 0;
|
||||
|
||||
public: // Callbacks for mapping methods
|
||||
virtual int instance_mapping_length(PyObject*) const;
|
||||
virtual PyObject* instance_mapping_subscript(PyObject*, PyObject*) const ;
|
||||
virtual int instance_mapping_ass_subscript(PyObject*, PyObject*, PyObject*) const;
|
||||
|
||||
public: // Callbacks for sequence methods
|
||||
virtual int instance_sequence_length(PyObject* obj) const;
|
||||
virtual PyObject* instance_sequence_concat(PyObject* obj, PyObject* other) const;
|
||||
virtual PyObject* instance_sequence_repeat(PyObject* obj, int n) const;
|
||||
virtual PyObject* instance_sequence_item(PyObject* obj, int n) const;
|
||||
virtual PyObject* instance_sequence_slice(PyObject* obj, int start, int finish) const;
|
||||
virtual int instance_sequence_ass_item(PyObject* obj, int n, PyObject* value) const;
|
||||
virtual int instance_sequence_ass_slice(PyObject* obj, int start, int finish, PyObject* value) const;
|
||||
|
||||
public: // Callbacks for number methods
|
||||
virtual PyObject* instance_number_add(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_subtract(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_multiply(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_divide(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_remainder(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_divmod(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_power(PyObject*, PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_negative(PyObject*) const;
|
||||
virtual PyObject* instance_number_positive(PyObject*) const;
|
||||
virtual PyObject* instance_number_absolute(PyObject*) const;
|
||||
virtual int instance_number_nonzero(PyObject*) const;
|
||||
virtual PyObject* instance_number_invert(PyObject*) const;
|
||||
virtual PyObject* instance_number_lshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_rshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_and(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_xor(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_or(PyObject*, PyObject*) const;
|
||||
virtual int instance_number_coerce(PyObject*, PyObject**, PyObject**) const;
|
||||
virtual PyObject* instance_number_int(PyObject*) const;
|
||||
virtual PyObject* instance_number_long(PyObject*) const;
|
||||
virtual PyObject* instance_number_float(PyObject*) const;
|
||||
virtual PyObject* instance_number_oct(PyObject*) const;
|
||||
virtual PyObject* instance_number_hex(PyObject*) const;
|
||||
|
||||
virtual PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
|
||||
|
||||
public: // Callbacks for rich comparisons
|
||||
virtual PyObject* instance_lt(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_le(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_eq(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_ne(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_gt(PyObject*, PyObject*) const;
|
||||
virtual PyObject* instance_ge(PyObject*, PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class type_object : public type_object_base
|
||||
{
|
||||
public:
|
||||
typedef T instance;
|
||||
|
||||
type_object(PyTypeObject* type_type, const char* name)
|
||||
: type_object_base(type_type)
|
||||
{
|
||||
assert(name != 0);
|
||||
this->tp_name = const_cast<char*>(name);
|
||||
}
|
||||
|
||||
type_object(PyTypeObject* type_type)
|
||||
: type_object_base(type_type)
|
||||
{
|
||||
this->tp_name = const_cast<char*>(typeid(instance).name());
|
||||
}
|
||||
|
||||
private: // Overridable behaviors.
|
||||
// Called when the reference count goes to zero. The default implementation
|
||||
// is "delete p". If you have not allocated your object with operator new or
|
||||
// you have other constraints, you'll need to override this
|
||||
virtual void dealloc(T* p) const;
|
||||
|
||||
private: // Implementation of type_object_base hooks. Do not reimplement in derived classes.
|
||||
void instance_dealloc(PyObject*) const;
|
||||
};
|
||||
|
||||
//
|
||||
// type objects
|
||||
//
|
||||
template <class Base>
|
||||
class callable : public Base
|
||||
{
|
||||
public:
|
||||
typedef callable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
callable(PyTypeObject* type_type, const char* name);
|
||||
callable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* kw) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class getattrable : public Base
|
||||
{
|
||||
public:
|
||||
typedef getattrable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
getattrable(PyTypeObject* type_type, const char* name);
|
||||
getattrable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_getattr(PyObject* obj, const char* name) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class setattrable : public Base
|
||||
{
|
||||
public:
|
||||
typedef setattrable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
setattrable(PyTypeObject* type_type, const char* name);
|
||||
setattrable(PyTypeObject* type_type);
|
||||
private:
|
||||
int instance_setattr(PyObject* obj, const char* name, PyObject* value) const;
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class reprable : public Base
|
||||
{
|
||||
public:
|
||||
typedef reprable properties; // Convenience for derived class construction
|
||||
typedef typename Base::instance instance;
|
||||
reprable(PyTypeObject* type_type, const char* name);
|
||||
reprable(PyTypeObject* type_type);
|
||||
private:
|
||||
PyObject* instance_repr(PyObject* obj) const;
|
||||
};
|
||||
|
||||
//
|
||||
// Member function definitions
|
||||
//
|
||||
|
||||
// type_object<>
|
||||
template <class T>
|
||||
void type_object<T>::instance_dealloc(PyObject* obj) const
|
||||
{
|
||||
this->dealloc(downcast<instance>(obj).get());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void type_object<T>::dealloc(T* obj) const
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
|
||||
// callable
|
||||
template <class Base>
|
||||
callable<Base>::callable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(call);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
callable<Base>::callable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(call);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* callable<Base>::instance_call(PyObject* obj, PyObject* args, PyObject* kw) const
|
||||
{
|
||||
return downcast<instance>(obj)->call(args, kw);
|
||||
}
|
||||
|
||||
// getattrable
|
||||
template <class Base>
|
||||
getattrable<Base>::getattrable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(getattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
getattrable<Base>::getattrable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(getattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* getattrable<Base>::instance_getattr(PyObject* obj, const char* name) const
|
||||
{
|
||||
return downcast<instance>(obj)->getattr(name);
|
||||
}
|
||||
|
||||
// setattrable
|
||||
template <class Base>
|
||||
setattrable<Base>::setattrable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(setattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
setattrable<Base>::setattrable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(setattr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
int setattrable<Base>::instance_setattr(PyObject* obj, const char* name, PyObject* value) const
|
||||
{
|
||||
return downcast<instance>(obj)->setattr(name, value);
|
||||
}
|
||||
|
||||
// reprable
|
||||
template <class Base>
|
||||
reprable<Base>::reprable(PyTypeObject* type_type, const char* name)
|
||||
: Base(type_type, name)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
reprable<Base>::reprable(PyTypeObject* type_type)
|
||||
: Base(type_type)
|
||||
{
|
||||
this->enable(repr);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
PyObject* reprable<Base>::instance_repr(PyObject* obj) const
|
||||
{
|
||||
return downcast<instance>(obj)->repr();
|
||||
}
|
||||
|
||||
// Helper class for optimized allocation of PODs: If two PODs
|
||||
// happen to contain identical byte patterns, they may share their
|
||||
// memory. Reference counting is used to free unused memory.
|
||||
// This is useful because method tables of related extension classes tend
|
||||
// to be identical, so less memory is needed for them.
|
||||
class shared_pod_manager
|
||||
{
|
||||
typedef std::pair<char*, std::size_t> holder;
|
||||
typedef std::vector<holder> storage;
|
||||
|
||||
public:
|
||||
static shared_pod_manager& obj();
|
||||
~shared_pod_manager();
|
||||
|
||||
// Allocate memory for POD T and fill it with zeros.
|
||||
// This memory is initially not shared.
|
||||
template <class T>
|
||||
static void create(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().create(sizeof(T)));
|
||||
}
|
||||
|
||||
// Decrement the refcount for the memory t points to. If the count
|
||||
// goes to zero, the memory is freed.
|
||||
template <class T>
|
||||
static void dispose(T* t)
|
||||
{
|
||||
obj().dec_ref(t, sizeof(T));
|
||||
}
|
||||
|
||||
// Attempt to share the memory t points to. If memory with the same
|
||||
// contents already exists, t is replaced by a pointer to this memory,
|
||||
// and t's old memory is disposed. Otherwise, t will be registered for
|
||||
// potential future sharing.
|
||||
template <class T>
|
||||
static void replace_if_equal(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().replace_if_equal(t, sizeof(T)));
|
||||
}
|
||||
|
||||
// Create a copy of t's memory that is guaranteed to be private to t.
|
||||
// Afterwards t points to the new memory, unless it was already private, in
|
||||
// which case there is no change (except that t's memory will no longer
|
||||
// be considered for future sharing - see raplade_if_equal())
|
||||
// This function *must* be called before the contents of (*t) can
|
||||
// be overwritten. Otherwise, inconsistencies and crashes may result.
|
||||
template <class T>
|
||||
static void make_unique_copy(T*& t)
|
||||
{
|
||||
t = reinterpret_cast<T*>(obj().make_unique_copy(t, sizeof(T)));
|
||||
}
|
||||
|
||||
private:
|
||||
void* replace_if_equal(void* pod, std::size_t size);
|
||||
void* make_unique_copy(void* pod, std::size_t size);
|
||||
void* create(std::size_t size);
|
||||
void dec_ref(void* pod, std::size_t size);
|
||||
void erase_from_list(void* pod);
|
||||
|
||||
struct compare;
|
||||
struct identical;
|
||||
|
||||
private:
|
||||
shared_pod_manager() {} // instance
|
||||
|
||||
#ifdef TYPE_OBJECT_BASE_STANDALONE_TEST
|
||||
public:
|
||||
#endif
|
||||
storage m_storage;
|
||||
};
|
||||
|
||||
|
||||
void add_capability(type_object_base::capability capability,
|
||||
PyTypeObject* dest);
|
||||
|
||||
// This macro gets the length of an array as a compile-time constant, and will
|
||||
// fail to compile if the parameter is a pointer.
|
||||
#ifdef __BORLANDC__ // smart implementation doesn't work for borland; maybe someone knows a workaround?
|
||||
# define PY_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#else
|
||||
# define PY_ARRAY_LENGTH(a) \
|
||||
(sizeof(::boost::python::detail::countof_validate(a, &(a))) ? sizeof(a) / sizeof((a)[0]) : 0)
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline void countof_validate(T* const, T* const*);
|
||||
|
||||
template<typename T>
|
||||
inline int countof_validate(const void*, T);
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // TYPES_DWA051800_H_
|
||||
39
include/boost/python/detail/void_adaptor.hpp
Normal file
39
include/boost/python/detail/void_adaptor.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// (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.
|
||||
|
||||
#ifndef VOID_ADAPTOR_DWA20011112_HPP
|
||||
# define VOID_ADAPTOR_DWA20011112_HPP
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
extern PyObject arbitrary_object;
|
||||
|
||||
template <class T>
|
||||
struct void_adaptor
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
|
||||
void_adaptor(T const& f)
|
||||
: m_f(f)
|
||||
{}
|
||||
|
||||
PyObject* operator()() const
|
||||
{
|
||||
m_f();
|
||||
return &arbitrary_object;
|
||||
}
|
||||
private:
|
||||
T m_f;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void_adaptor<T> make_void_adaptor(T const& f)
|
||||
{
|
||||
return void_adaptor<T>(f);
|
||||
}
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // VOID_ADAPTOR_DWA20011112_HPP
|
||||
|
||||
118
include/boost/python/detail/wrap_python.hpp
Normal file
118
include/boost/python/detail/wrap_python.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
// This file serves as a wrapper around <Python.h> which allows it to be
|
||||
// compiled with GCC 2.95.2 under Win32 and which disables the default MSVC
|
||||
// behavior so that a program may be compiled in debug mode without requiring a
|
||||
// special debugging build of the Python library.
|
||||
|
||||
|
||||
// To use the Python debugging library, #define BOOST_DEBUG_PYTHON on the
|
||||
// compiler command-line.
|
||||
|
||||
// Revision History:
|
||||
// 05 Mar 01 Suppress warnings under Cygwin with Python 2.0 (Dave Abrahams)
|
||||
// 04 Mar 01 Rolled in some changes from the Dragon fork (Dave Abrahams)
|
||||
// 01 Mar 01 define PyObject_INIT() for Python 1.x (Dave Abrahams)
|
||||
|
||||
|
||||
#include <patchlevel.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
# ifndef BOOST_DEBUG_PYTHON
|
||||
# undef _DEBUG // Don't let Python force the debug library just because we're debugging.
|
||||
# define DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Some things we need in order to get Python.h to work with compilers other
|
||||
// than MSVC on Win32
|
||||
//
|
||||
#if defined(_WIN32)
|
||||
# if defined(__GNUC__) && defined(__CYGWIN__)
|
||||
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 2
|
||||
typedef int pid_t;
|
||||
# define WORD_BIT 32
|
||||
# define hypot _hypot
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
# if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||
# define HAVE_CLOCK
|
||||
# define HAVE_STRFTIME
|
||||
# define HAVE_STRERROR
|
||||
# endif
|
||||
# define NT_THREADS
|
||||
# define WITH_THREAD
|
||||
# ifndef NETSCAPE_PI
|
||||
# define USE_SOCKET
|
||||
# endif
|
||||
|
||||
# ifdef USE_DL_IMPORT
|
||||
# define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE
|
||||
# endif
|
||||
|
||||
# ifdef USE_DL_EXPORT
|
||||
# define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE
|
||||
# define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
|
||||
# endif
|
||||
|
||||
# define HAVE_LONG_LONG 1
|
||||
# define LONG_LONG long long
|
||||
|
||||
# elif defined(__MWERKS__)
|
||||
|
||||
# ifndef _MSC_VER
|
||||
# define PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H 1
|
||||
# define _MSC_VER 900
|
||||
# endif
|
||||
|
||||
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2
|
||||
# include <config.h>
|
||||
# else
|
||||
# include <pyconfig.h>
|
||||
# endif
|
||||
# undef hypot // undo the evil #define left by Python.
|
||||
|
||||
# elif defined(__BORLANDC__)
|
||||
# if PY_MAJOR_VERSION < 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2
|
||||
# include <config.h>
|
||||
# else
|
||||
# include <pyconfig.h>
|
||||
# endif
|
||||
# undef HAVE_HYPOT
|
||||
# define HAVE_HYPOT 1
|
||||
# elif defined(_MSC_VER)
|
||||
# ifdef __cplusplus
|
||||
# include <limits> // prevents Python.h from defining LONGLONG_MAX, LONGLONG_MIN, and ULONGLONG_MAX
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef PY_MSC_VER_DEFINED_FROM_WRAP_PYTHON_H
|
||||
# undef _MSC_VER
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
|
||||
# define _DEBUG
|
||||
#endif
|
||||
|
||||
#if !defined(PY_MAJOR_VERSION) || PY_MAJOR_VERSION < 2
|
||||
# define PyObject_INIT(op, typeobj) \
|
||||
( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
|
||||
#endif
|
||||
|
||||
#ifdef __MWERKS__
|
||||
# pragma warn_possunwant off
|
||||
#elif _MSC_VER
|
||||
# pragma warning(disable:4786)
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
// 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
|
||||
@@ -1,41 +0,0 @@
|
||||
// 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
|
||||
@@ -1,37 +0,0 @@
|
||||
// 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
|
||||
@@ -1,76 +0,0 @@
|
||||
// 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
|
||||
@@ -1,24 +0,0 @@
|
||||
// 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
|
||||
@@ -1,33 +0,0 @@
|
||||
// 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
|
||||
@@ -1,36 +0,0 @@
|
||||
// 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
|
||||
@@ -1,124 +0,0 @@
|
||||
// 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
|
||||
@@ -1,80 +0,0 @@
|
||||
// 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
|
||||
@@ -1,217 +0,0 @@
|
||||
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
|
||||
287
src/conversions.cpp
Normal file
287
src/conversions.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 05 Apr 01 added: from_python std::string type checking (rwgk)
|
||||
// 12 Mar 01 Python 1.5.2 fixes (Ralf W. Grosse-Kunstleve)
|
||||
// 11 Mar 01 std::string *MAY* include nulls (Alex Martelli)
|
||||
// 04 Mar 01 std::complex<> fixes for MSVC (Dave Abrahams)
|
||||
// 03 Mar 01 added: converters for [plain] char (Ralf W. Grosse-Kunstleve)
|
||||
|
||||
#include <boost/python/conversions.hpp>
|
||||
#include <boost/python/detail/void_adaptor.hpp>
|
||||
#include <typeinfo>
|
||||
#include <exception>
|
||||
#ifndef BOOST_NO_LIMITS
|
||||
# include <boost/cast.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// IMPORTANT: this function may only be called from within a catch block!
|
||||
PyObject* handle_exception_impl(object_functor_base const& f)
|
||||
{
|
||||
try
|
||||
{
|
||||
return f();
|
||||
}
|
||||
catch(const boost::python::error_already_set&)
|
||||
{
|
||||
// The python error reporting has already been handled.
|
||||
}
|
||||
catch(const std::bad_alloc&)
|
||||
{
|
||||
PyErr_NoMemory();
|
||||
}
|
||||
catch(const std::exception& x)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, x.what());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handle_exception(void (*f)())
|
||||
{
|
||||
handle_exception(
|
||||
boost::python::detail::make_void_adaptor(f));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
void expect_complex(PyObject* p)
|
||||
{
|
||||
if (!PyComplex_Check(p))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "expected a complex number");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace boost::python::detail
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
long from_python(PyObject* p, boost::python::type<long>)
|
||||
{
|
||||
// Why am I clearing the error here before trying to convert? I know there's a reason...
|
||||
long result;
|
||||
{
|
||||
result = PyInt_AsLong(p);
|
||||
if (PyErr_Occurred())
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double from_python(PyObject* p, boost::python::type<double>)
|
||||
{
|
||||
double result;
|
||||
{
|
||||
result = PyFloat_AsDouble(p);
|
||||
if (PyErr_Occurred())
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T integer_from_python(PyObject* p, boost::python::type<T>)
|
||||
{
|
||||
const long long_result = from_python(p, boost::python::type<long>());
|
||||
|
||||
#ifndef BOOST_NO_LIMITS
|
||||
try
|
||||
{
|
||||
return boost::numeric_cast<T>(long_result);
|
||||
}
|
||||
catch(const boost::bad_numeric_cast&)
|
||||
#else
|
||||
if (static_cast<T>(long_result) == long_result)
|
||||
{
|
||||
return static_cast<T>(long_result);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
char buffer[256];
|
||||
const char message[] = "%ld out of range for %s";
|
||||
sprintf(buffer, message, long_result, typeid(T).name());
|
||||
PyErr_SetString(PyExc_ValueError, buffer);
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406
|
||||
return 0; // Not smart enough to know that the catch clause always rethrows
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* integer_to_python(T value)
|
||||
{
|
||||
long value_as_long;
|
||||
|
||||
#ifndef BOOST_NO_LIMITS
|
||||
try
|
||||
{
|
||||
value_as_long = boost::numeric_cast<long>(value);
|
||||
}
|
||||
catch(const boost::bad_numeric_cast&)
|
||||
#else
|
||||
value_as_long = static_cast<long>(value);
|
||||
if (value_as_long != value)
|
||||
#endif
|
||||
{
|
||||
const char message[] = "value out of range for Python int";
|
||||
PyErr_SetString(PyExc_ValueError, message);
|
||||
throw boost::python::error_already_set();
|
||||
}
|
||||
|
||||
return to_python(value_as_long);
|
||||
}
|
||||
|
||||
int from_python(PyObject* p, boost::python::type<int> type)
|
||||
{
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(unsigned int i)
|
||||
{
|
||||
return integer_to_python(i);
|
||||
}
|
||||
|
||||
unsigned int from_python(PyObject* p, boost::python::type<unsigned int> type)
|
||||
{
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
short from_python(PyObject* p, boost::python::type<short> type)
|
||||
{
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
float from_python(PyObject* p, boost::python::type<float>)
|
||||
{
|
||||
return static_cast<float>(from_python(p, boost::python::type<double>()));
|
||||
}
|
||||
|
||||
PyObject* to_python(unsigned short i)
|
||||
{
|
||||
return integer_to_python(i);
|
||||
}
|
||||
|
||||
unsigned short from_python(PyObject* p, boost::python::type<unsigned short> type)
|
||||
{
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(char c)
|
||||
{
|
||||
if (c == '\0') return PyString_FromString("");
|
||||
return PyString_FromStringAndSize(&c, 1);
|
||||
}
|
||||
|
||||
char from_python(PyObject* p, boost::python::type<char>)
|
||||
{
|
||||
int l = -1;
|
||||
if (PyString_Check(p)) l = PyString_Size(p);
|
||||
if (l < 0 || l > 1) {
|
||||
PyErr_SetString(PyExc_TypeError, "expected string of length 0 or 1");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
if (l == 0) return '\0';
|
||||
return PyString_AsString(p)[0];
|
||||
}
|
||||
|
||||
PyObject* to_python(unsigned char i)
|
||||
{
|
||||
return integer_to_python(i);
|
||||
}
|
||||
|
||||
unsigned char from_python(PyObject* p, boost::python::type<unsigned char> type)
|
||||
{
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(signed char i)
|
||||
{
|
||||
return integer_to_python(i);
|
||||
}
|
||||
|
||||
signed char from_python(PyObject* p, boost::python::type<signed char> type)
|
||||
{
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(unsigned long x)
|
||||
{
|
||||
return integer_to_python(x);
|
||||
}
|
||||
|
||||
unsigned long from_python(PyObject* p, boost::python::type<unsigned long> type)
|
||||
{
|
||||
return integer_from_python(p, type);
|
||||
}
|
||||
|
||||
void from_python(PyObject* p, boost::python::type<void>)
|
||||
{
|
||||
if (p != Py_None) {
|
||||
PyErr_SetString(PyExc_TypeError, "expected argument of type None");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
}
|
||||
|
||||
const char* from_python(PyObject* p, boost::python::type<const char*>)
|
||||
{
|
||||
const char* s = PyString_AsString(p);
|
||||
if (!s)
|
||||
throw boost::python::argument_error();
|
||||
return s;
|
||||
}
|
||||
|
||||
PyObject* to_python(const std::string& s)
|
||||
{
|
||||
return PyString_FromStringAndSize(s.data(), s.size());
|
||||
}
|
||||
|
||||
std::string from_python(PyObject* p, boost::python::type<std::string>)
|
||||
{
|
||||
if (! PyString_Check(p)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expected a string");
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
return std::string(PyString_AsString(p), PyString_Size(p));
|
||||
}
|
||||
|
||||
bool from_python(PyObject* p, boost::python::type<bool>)
|
||||
{
|
||||
int value = from_python(p, boost::python::type<int>());
|
||||
if (value == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC6_OR_EARLIER
|
||||
// An optimizer bug prevents these from being inlined.
|
||||
PyObject* to_python(double d)
|
||||
{
|
||||
return PyFloat_FromDouble(d);
|
||||
}
|
||||
|
||||
PyObject* to_python(float f)
|
||||
{
|
||||
return PyFloat_FromDouble(f);
|
||||
}
|
||||
#endif // BOOST_MSVC6_OR_EARLIER
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// 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
|
||||
@@ -1,35 +0,0 @@
|
||||
// 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
|
||||
@@ -1,170 +0,0 @@
|
||||
// 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
|
||||
@@ -1,67 +0,0 @@
|
||||
// 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
|
||||
@@ -1,35 +0,0 @@
|
||||
// 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
|
||||
@@ -1,23 +0,0 @@
|
||||
// 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
|
||||
@@ -1,29 +0,0 @@
|
||||
// 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
|
||||
87
src/cross_module.cpp
Normal file
87
src/cross_module.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* (C) Copyright Ralf W. Grosse-Kunstleve 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.
|
||||
|
||||
Revision History:
|
||||
17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve)
|
||||
*/
|
||||
|
||||
# include <boost/python/cross_module.hpp>
|
||||
namespace python = boost::python;
|
||||
# include <stdio.h> // MSVC6.0SP4 does not know std::fprintf
|
||||
# include <string.h> // MSVC6.0SP4 does not know std::strcmp
|
||||
|
||||
namespace {
|
||||
|
||||
PyObject* get_module_dict(const char* module_name)
|
||||
{
|
||||
python::ref module_obj(PyImport_ImportModule((char*) module_name));
|
||||
PyObject* module_dict = PyModule_GetDict(module_obj.get());
|
||||
if (module_dict == 0) throw python::import_error();
|
||||
return module_dict;
|
||||
}
|
||||
}
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
const char* converters_attribute_name = "__converters__";
|
||||
|
||||
void* import_converter_object(const std::string& module_name,
|
||||
const std::string& py_class_name,
|
||||
const std::string& attribute_name)
|
||||
{
|
||||
static std::string err;
|
||||
PyObject* module_dict = get_module_dict(const_cast<char*>(module_name.c_str()));
|
||||
PyObject* py_class = PyDict_GetItemString(module_dict, const_cast<char*>(py_class_name.c_str()));
|
||||
if (py_class == 0) {
|
||||
err = std::string("module ") + module_name + " has no attribute " + py_class_name;
|
||||
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
|
||||
throw python::import_error();
|
||||
}
|
||||
python::ref c_obj(PyObject_GetAttrString(py_class, const_cast<char*>(attribute_name.c_str())), ref::null_ok);
|
||||
if (c_obj.get() == 0) {
|
||||
err = std::string("object ") + module_name + "." + py_class_name
|
||||
+ " has no attribute " + attribute_name;
|
||||
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
|
||||
throw python::import_error();
|
||||
}
|
||||
if (! PyCObject_Check(c_obj.get())) {
|
||||
err = std::string("object ") + module_name + "." + py_class_name + "."
|
||||
+ attribute_name + " is not a PyCObject";
|
||||
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(err.c_str()));
|
||||
throw python::import_error();
|
||||
}
|
||||
return PyCObject_AsVoidPtr(c_obj.get());
|
||||
}
|
||||
|
||||
void check_export_converters_api(const int importing_major,
|
||||
const int importing_minor,
|
||||
const int imported_major,
|
||||
const int imported_minor)
|
||||
{
|
||||
if (importing_major != imported_major) {
|
||||
// Python uses fprintf(stderr, ...) for API warnings.
|
||||
fprintf(stderr,
|
||||
"Fatal: export_converters_api mismatch:"
|
||||
" Importing module = %d.%d"
|
||||
" Imported module = %d.%d\n",
|
||||
importing_major, importing_minor,
|
||||
imported_major, imported_minor);
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Fatal: export_converters_api mismatch");
|
||||
throw import_error();
|
||||
}
|
||||
if (importing_minor != imported_minor) {
|
||||
// Python uses fprintf(stderr, ...) for API warnings.
|
||||
fprintf(stderr,
|
||||
"Warning: export_converters_api mismatch:"
|
||||
" Importing module = %d.%d"
|
||||
" Imported module = %d.%d\n",
|
||||
importing_major, importing_minor,
|
||||
imported_major, imported_minor);
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
687
src/extension_class.cpp
Normal file
687
src/extension_class.cpp
Normal file
@@ -0,0 +1,687 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 04 Mar 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||
|
||||
#include <boost/python/detail/extension_class.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <cstring>
|
||||
|
||||
namespace boost { namespace python {
|
||||
namespace detail {
|
||||
|
||||
struct operator_dispatcher
|
||||
: public PyObject
|
||||
{
|
||||
static PyTypeObject type_obj;
|
||||
static PyNumberMethods number_methods;
|
||||
|
||||
static operator_dispatcher* create(const ref& o, const ref& s);
|
||||
|
||||
ref m_object;
|
||||
ref m_self;
|
||||
|
||||
// data members for allocation/deallocation optimization
|
||||
operator_dispatcher* m_free_list_link;
|
||||
static operator_dispatcher* free_list;
|
||||
|
||||
private:
|
||||
// only accessible through create()
|
||||
operator_dispatcher(const ref& o, const ref& s);
|
||||
};
|
||||
|
||||
operator_dispatcher* operator_dispatcher::free_list = 0;
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
inline PyObject* to_python(boost::python::detail::operator_dispatcher* n) { return n; }
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
tuple standard_coerce(ref l, ref r)
|
||||
{
|
||||
// Introduced sequence points for exception-safety.
|
||||
ref first(detail::operator_dispatcher::create(l, l));
|
||||
|
||||
ref second(r->ob_type == &detail::operator_dispatcher::type_obj
|
||||
? r
|
||||
: ref(detail::operator_dispatcher::create(r, ref())));
|
||||
|
||||
return tuple(first, second);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
enum { unwrap_exception_code = -1000 };
|
||||
|
||||
int unwrap_args(PyObject* left, PyObject* right, PyObject*& self, PyObject*& other)
|
||||
{
|
||||
if (left->ob_type != &operator_dispatcher::type_obj ||
|
||||
right->ob_type != &operator_dispatcher::type_obj)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_args(): expecting operator_dispatcher arguments only!");
|
||||
return unwrap_exception_code;
|
||||
}
|
||||
|
||||
typedef reference<operator_dispatcher> DPtr;
|
||||
DPtr lwrapper(static_cast<operator_dispatcher*>(left), DPtr::increment_count);
|
||||
DPtr rwrapper(static_cast<operator_dispatcher*>(right), DPtr::increment_count);
|
||||
|
||||
if (lwrapper->m_self.get() != 0)
|
||||
{
|
||||
self = lwrapper->m_self.get();
|
||||
other = rwrapper->m_object.get();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
self = rwrapper->m_self.get();
|
||||
other = lwrapper->m_object.get();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int unwrap_pow_args(PyObject* left, PyObject* right, PyObject* m,
|
||||
PyObject*& self, PyObject*& first, PyObject*& second)
|
||||
{
|
||||
if (left->ob_type != &operator_dispatcher::type_obj ||
|
||||
right->ob_type != &operator_dispatcher::type_obj ||
|
||||
m->ob_type != &operator_dispatcher::type_obj)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "operator_dispatcher::unwrap_pow_args(): expecting operator_dispatcher arguments only!");
|
||||
return unwrap_exception_code;
|
||||
}
|
||||
|
||||
typedef reference<operator_dispatcher> DPtr;
|
||||
DPtr lwrapper(static_cast<operator_dispatcher*>(left), DPtr::increment_count);
|
||||
DPtr rwrapper(static_cast<operator_dispatcher*>(right), DPtr::increment_count);
|
||||
DPtr mwrapper(static_cast<operator_dispatcher*>(m), DPtr::increment_count);
|
||||
|
||||
if (lwrapper->m_self.get() != 0)
|
||||
{
|
||||
self = lwrapper->m_self.get();
|
||||
first = rwrapper->m_object.get();
|
||||
second = mwrapper->m_object.get();
|
||||
return 0;
|
||||
}
|
||||
else if (rwrapper->m_self.get() != 0)
|
||||
{
|
||||
self = rwrapper->m_self.get();
|
||||
first = lwrapper->m_object.get();
|
||||
second = mwrapper->m_object.get();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self = mwrapper->m_self.get();
|
||||
first = lwrapper->m_object.get();
|
||||
second = rwrapper->m_object.get();
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
extension_instance* get_extension_instance(PyObject* p)
|
||||
{
|
||||
// The object's type will just be some class_t<extension_instance> object,
|
||||
// but if its meta-type is right, then it is an extension_instance.
|
||||
if (p->ob_type->ob_type != extension_meta_class())
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
|
||||
throw boost::python::argument_error();
|
||||
}
|
||||
return static_cast<extension_instance*>(p);
|
||||
}
|
||||
|
||||
void
|
||||
extension_instance::add_implementation(std::auto_ptr<instance_holder_base> holder)
|
||||
{
|
||||
for (held_objects::const_iterator p = m_wrapped_objects.begin();
|
||||
p != m_wrapped_objects.end(); ++p)
|
||||
{
|
||||
if (typeid(*holder) == typeid(**p))
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "Base class already initialized");
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
m_wrapped_objects.push_back(holder.release());
|
||||
}
|
||||
|
||||
extension_instance::extension_instance(PyTypeObject* class_)
|
||||
: instance(class_)
|
||||
{
|
||||
}
|
||||
|
||||
extension_instance::~extension_instance()
|
||||
{
|
||||
for (held_objects::const_iterator p = m_wrapped_objects.begin(),
|
||||
finish = m_wrapped_objects.end();
|
||||
p != finish; ++p)
|
||||
{
|
||||
delete *p;
|
||||
}
|
||||
}
|
||||
|
||||
meta_class<extension_instance>* extension_meta_class()
|
||||
{
|
||||
static meta_class<extension_instance> result;
|
||||
return &result;
|
||||
}
|
||||
|
||||
typedef class_t<extension_instance> extension_class_t;
|
||||
|
||||
bool is_subclass(const extension_class_t* derived,
|
||||
const PyObject* possible_base)
|
||||
{
|
||||
|
||||
tuple bases = derived->bases();
|
||||
|
||||
for (std::size_t i = 0, size = bases.size(); i < size; ++i)
|
||||
{
|
||||
const PyObject* base = bases[i].get();
|
||||
|
||||
if (base == possible_base)
|
||||
return true;
|
||||
|
||||
if (base->ob_type == extension_meta_class())
|
||||
{
|
||||
const extension_class_t* base_class = downcast<const extension_class_t>(base);
|
||||
if (is_subclass(base_class, possible_base))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true iff obj is an obj of target_class
|
||||
bool is_instance(extension_instance* obj,
|
||||
class_t<extension_instance>* target_class)
|
||||
{
|
||||
if (obj->ob_type == target_class)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
return is_subclass(
|
||||
downcast<class_t<extension_instance> >(obj->ob_type).get(),
|
||||
as_object(target_class));
|
||||
}
|
||||
}
|
||||
|
||||
void two_string_error(PyObject* exception_object, const char* format, const char* s1, const char* s2)
|
||||
{
|
||||
char buffer[256];
|
||||
std::size_t format_length = BOOST_CSTD_::strlen(format);
|
||||
std::size_t length1 = BOOST_CSTD_::strlen(s1);
|
||||
std::size_t length2 = BOOST_CSTD_::strlen(s2);
|
||||
|
||||
std::size_t additional_length = length1 + length2;
|
||||
if (additional_length + format_length > format_length - 1)
|
||||
{
|
||||
std::size_t difference = sizeof(buffer) - 1 - additional_length;
|
||||
length1 -= difference / 2;
|
||||
additional_length -= difference / 2;
|
||||
}
|
||||
|
||||
sprintf(buffer, format, length1, s1, length2, s2);
|
||||
|
||||
PyErr_SetString(exception_object, buffer);
|
||||
if (exception_object == PyExc_TypeError)
|
||||
throw argument_error();
|
||||
else
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
// This is called when an attempt has been made to convert the given obj to
|
||||
// a C++ type for which it doesn't have any obj data. In that case, either
|
||||
// the obj was not derived from the target_class, or the appropriate
|
||||
// __init__ function wasn't called to initialize the obj data of the target class.
|
||||
void report_missing_instance_data(
|
||||
extension_instance* obj, // The object being converted
|
||||
class_t<extension_instance>* target_class, // the extension class of the C++ type
|
||||
const std::type_info& target_typeid, // The typeid of the C++ type
|
||||
bool target_is_ptr)
|
||||
{
|
||||
char buffer[256];
|
||||
if (is_instance(obj, target_class))
|
||||
{
|
||||
if (target_is_ptr)
|
||||
{
|
||||
two_string_error(PyExc_RuntimeError,
|
||||
"Object of extension class '%.*s' does not wrap <%.*s>.",
|
||||
obj->ob_type->tp_name, target_typeid.name());
|
||||
}
|
||||
else
|
||||
{
|
||||
const char message[] = "__init__ function for extension class '%.*s' was never called.";
|
||||
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1,
|
||||
target_class->tp_name);
|
||||
}
|
||||
PyErr_SetString(PyExc_RuntimeError, buffer);
|
||||
}
|
||||
else if (target_class == 0)
|
||||
{
|
||||
const char message[] = "Cannot convert to <%.*s>; its Python class was never created or has been deleted.";
|
||||
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, target_typeid.name());
|
||||
PyErr_SetString(PyExc_RuntimeError, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
two_string_error(PyExc_TypeError, "extension class '%.*s' is not convertible into '%.*s'.",
|
||||
obj->ob_type->tp_name, target_class->tp_name);
|
||||
}
|
||||
}
|
||||
|
||||
void report_missing_instance_data(
|
||||
extension_instance* obj, // The object being converted
|
||||
class_t<extension_instance>* target_class, // the extension class of the C++ type
|
||||
const std::type_info& target_typeid) // The typeid of the C++ type
|
||||
{
|
||||
report_missing_instance_data(obj, target_class, target_typeid, false);
|
||||
}
|
||||
|
||||
void report_missing_ptr_data(
|
||||
extension_instance* obj, // The object being converted
|
||||
class_t<extension_instance>* target_class, // the extension class of the C++ type
|
||||
const std::type_info& target_typeid) // The typeid of the C++ type
|
||||
{
|
||||
report_missing_instance_data(obj, target_class, target_typeid, true);
|
||||
}
|
||||
|
||||
void report_missing_class_object(const std::type_info& info)
|
||||
{
|
||||
char buffer[256];
|
||||
const char message[] = "Cannot convert <%.*s> to python; its Python class was never created or has been deleted.";
|
||||
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name());
|
||||
PyErr_SetString(PyExc_RuntimeError, buffer);
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
void report_released_smart_pointer(const std::type_info& info)
|
||||
{
|
||||
char buffer[256];
|
||||
const char message[] = "Converting from python, pointer or smart pointer to <%.*s> is NULL.";
|
||||
sprintf(buffer, message, sizeof(buffer) - sizeof(message) - 1, info.name());
|
||||
PyErr_SetString(PyExc_RuntimeError, buffer);
|
||||
throw argument_error();
|
||||
}
|
||||
|
||||
read_only_setattr_function::read_only_setattr_function(const char* name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
PyObject* read_only_setattr_function::do_call(PyObject* /*args*/, PyObject* /*keywords*/) const
|
||||
{
|
||||
PyErr_SetObject(PyExc_AttributeError, ("'" + m_name + "' attribute is read-only").get());
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* read_only_setattr_function::description() const
|
||||
{
|
||||
return "uncallable";
|
||||
}
|
||||
|
||||
extension_class_base::extension_class_base(const char* name)
|
||||
: class_t<extension_instance>(
|
||||
extension_meta_class(), string(name), tuple(), dictionary())
|
||||
{
|
||||
}
|
||||
|
||||
// This function is used in from_python() to convert wrapped classes that are
|
||||
// related by inheritance. The problem is this: although C++ provides all necessary
|
||||
// conversion operators, source and target of a conversion must be known at compile
|
||||
// time. However, in Python we want to convert classes at runtime. The solution is to
|
||||
// generate conversion functions at compile time, register them within the appropriate
|
||||
// class objects and call them when a particular runtime conversion is required.
|
||||
|
||||
// If functions for any possible conversion have to be stored, their number will grow
|
||||
// qudratically. To reduce this number, we actually store only conversion functions
|
||||
// between adjacent levels in the inheritance tree. By traversing the tree recursively,
|
||||
// we can build any allowed conversion as a concatenation of simple conversions. This
|
||||
// traversal is done in the functions try_base_class_conversions() and
|
||||
// try_derived_class_conversions(). If a particular conversion is impossible, all
|
||||
// conversion functions will return a NULL pointer.
|
||||
|
||||
// The function extract_object_from_holder() attempts to actually extract the pointer
|
||||
// to the contained object from an instance_holder_base (a wrapper class). A conversion
|
||||
// of the held object to 'T *' is allowed when the conversion
|
||||
// 'dynamic_cast<instance_holder<T> *>(an_instance_holder_base)' succeeds.
|
||||
void* extension_class_base::try_class_conversions(instance_holder_base* object) const
|
||||
{
|
||||
void* result = try_derived_class_conversions(object);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (!object->held_by_value())
|
||||
return try_base_class_conversions(object);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* extension_class_base::try_base_class_conversions(instance_holder_base* object) const
|
||||
{
|
||||
for (std::size_t i = 0; i < base_classes().size(); ++i)
|
||||
{
|
||||
if (base_classes()[i].convert == 0)
|
||||
continue;
|
||||
void* result1 = base_classes()[i].class_object->extract_object_from_holder(object);
|
||||
if (result1)
|
||||
return (*base_classes()[i].convert)(result1);
|
||||
|
||||
void* result2 = base_classes()[i].class_object->try_base_class_conversions(object);
|
||||
if (result2)
|
||||
return (*base_classes()[i].convert)(result2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* extension_class_base::try_derived_class_conversions(instance_holder_base* object) const
|
||||
{
|
||||
for (std::size_t i = 0; i < derived_classes().size(); ++i)
|
||||
{
|
||||
void* result1 = derived_classes()[i].class_object->extract_object_from_holder(object);
|
||||
if (result1)
|
||||
return (*derived_classes()[i].convert)(result1);
|
||||
|
||||
void* result2 = derived_classes()[i].class_object->try_derived_class_conversions(object);
|
||||
if (result2)
|
||||
return (*derived_classes()[i].convert)(result2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void extension_class_base::add_method(function* method, const char* name)
|
||||
{
|
||||
add_method(reference<function>(method), name);
|
||||
}
|
||||
|
||||
void extension_class_base::add_method(reference<function> method, const char* name)
|
||||
{
|
||||
// Add the attribute to the computed target
|
||||
function::add_to_namespace(method, name, this->dict().get());
|
||||
|
||||
// If it is a special member function it should be enabled both here and there.
|
||||
detail::enable_named_method(this, name);
|
||||
}
|
||||
|
||||
void extension_class_base::add_constructor_object(function* init_fn)
|
||||
{
|
||||
add_method(init_fn, "__init__");
|
||||
}
|
||||
|
||||
void extension_class_base::add_setter_method(function* setter_, const char* name)
|
||||
{
|
||||
reference<function> setter(setter_);
|
||||
add_method(setter, (detail::setattr_string() + name + "__").c_str());
|
||||
}
|
||||
|
||||
void extension_class_base::add_getter_method(function* getter_, const char* name)
|
||||
{
|
||||
reference<function> getter(getter_);
|
||||
add_method(getter, (detail::getattr_string() + name + "__").c_str());
|
||||
}
|
||||
|
||||
void extension_class_base::set_attribute(const char* name, PyObject* x_)
|
||||
{
|
||||
ref x(x_);
|
||||
set_attribute(name, x);
|
||||
}
|
||||
|
||||
void extension_class_base::set_attribute(const char* name, ref x)
|
||||
{
|
||||
dict().set_item(string(name), x);
|
||||
if (PyCallable_Check(x.get()))
|
||||
detail::enable_named_method(this, name);
|
||||
}
|
||||
|
||||
operator_dispatcher::operator_dispatcher(const ref& o, const ref& s)
|
||||
: m_object(o), m_self(s), m_free_list_link(0)
|
||||
|
||||
{
|
||||
PyObject* self = this;
|
||||
PyObject_INIT(self, &type_obj);
|
||||
}
|
||||
|
||||
operator_dispatcher*
|
||||
operator_dispatcher::create(const ref& object, const ref& self)
|
||||
{
|
||||
operator_dispatcher* const result = free_list;
|
||||
if (result == 0)
|
||||
return new operator_dispatcher(object, self);
|
||||
|
||||
free_list = result->m_free_list_link;
|
||||
result->m_object = object;
|
||||
result->m_self = self;
|
||||
|
||||
PyObject* result_as_pyobject = result;
|
||||
PyObject_INIT(result_as_pyobject, &type_obj);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void operator_dispatcher_dealloc(PyObject* self)
|
||||
{
|
||||
operator_dispatcher* obj = static_cast<operator_dispatcher*>(self);
|
||||
obj->m_free_list_link = operator_dispatcher::free_list;
|
||||
operator_dispatcher::free_list = obj;
|
||||
obj->m_object.reset();
|
||||
obj->m_self.reset();
|
||||
}
|
||||
|
||||
int operator_dispatcher_coerce(PyObject** l, PyObject** r)
|
||||
{
|
||||
Py_INCREF(*l);
|
||||
PyObject* new_r = handle_exception(
|
||||
bind(operator_dispatcher::create,
|
||||
ref(*r, ref::increment_count),
|
||||
ref()));
|
||||
if (new_r)
|
||||
{
|
||||
*r = new_r;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define PY_DEFINE_OPERATOR(id, symbol) \
|
||||
PyObject* operator_dispatcher_call_##id(PyObject* left, PyObject* right) \
|
||||
{ \
|
||||
/* unwrap the arguments from their OperatorDispatcher */ \
|
||||
PyObject* self; \
|
||||
PyObject* other; \
|
||||
int reverse = unwrap_args(left, right, self, other); \
|
||||
if (reverse == unwrap_exception_code) \
|
||||
return 0; \
|
||||
\
|
||||
/* call the function */ \
|
||||
PyObject* result = \
|
||||
PyEval_CallMethod(self, \
|
||||
const_cast<char*>(reverse ? "__r" #id "__" : "__" #id "__"), \
|
||||
const_cast<char*>("(O)"), \
|
||||
other); \
|
||||
if (result == 0 && PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)) \
|
||||
{ \
|
||||
PyErr_Clear(); \
|
||||
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for " #symbol); \
|
||||
} \
|
||||
return result; \
|
||||
}
|
||||
|
||||
PY_DEFINE_OPERATOR(add, +)
|
||||
PY_DEFINE_OPERATOR(sub, -)
|
||||
PY_DEFINE_OPERATOR(mul, *)
|
||||
PY_DEFINE_OPERATOR(div, /)
|
||||
PY_DEFINE_OPERATOR(mod, %)
|
||||
PY_DEFINE_OPERATOR(divmod, divmod)
|
||||
PY_DEFINE_OPERATOR(lshift, <<)
|
||||
PY_DEFINE_OPERATOR(rshift, >>)
|
||||
PY_DEFINE_OPERATOR(and, &)
|
||||
PY_DEFINE_OPERATOR(xor, ^)
|
||||
PY_DEFINE_OPERATOR(or, |)
|
||||
|
||||
/* coercion rules for heterogeneous pow():
|
||||
pow(Foo, int): left, right coerced; m: None => reverse = 0
|
||||
pow(int, Foo): left, right coerced; m: None => reverse = 1
|
||||
pow(Foo, int, int): left, right, m coerced => reverse = 0
|
||||
pow(int, Foo, int): left, right, m coerced => reverse = 1
|
||||
pow(int, int, Foo): left, right, m coerced => reverse = 2
|
||||
pow(Foo, Foo, int): left, right coerced; m coerced twice => reverse = 0
|
||||
pow(Foo, int, Foo): left, right, m coerced => reverse = 0
|
||||
pow(int, Foo, Foo): left, right, m coerced => reverse = 1
|
||||
*/
|
||||
PyObject* operator_dispatcher_call_pow(PyObject* left, PyObject* right, PyObject* m)
|
||||
{
|
||||
int reverse;
|
||||
PyObject* self;
|
||||
PyObject* first;
|
||||
PyObject* second;
|
||||
|
||||
if (m->ob_type == Py_None->ob_type)
|
||||
{
|
||||
reverse = unwrap_args(left, right, self, first);
|
||||
second = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
reverse = unwrap_pow_args(left, right, m, self, first, second);
|
||||
}
|
||||
|
||||
if (reverse == unwrap_exception_code)
|
||||
return 0;
|
||||
|
||||
// call the function
|
||||
PyObject* result =
|
||||
PyEval_CallMethod(self,
|
||||
const_cast<char*>((reverse == 0)
|
||||
? "__pow__"
|
||||
: (reverse == 1)
|
||||
? "__rpow__"
|
||||
: "__rrpow__"),
|
||||
const_cast<char*>("(OO)"),
|
||||
first, second);
|
||||
if (result == 0 &&
|
||||
(PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_TypeError) ||
|
||||
PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)))
|
||||
{
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int operator_dispatcher_call_cmp(PyObject* left, PyObject* right)
|
||||
{
|
||||
// unwrap the arguments from their OperatorDispatcher
|
||||
PyObject* self;
|
||||
PyObject* other;
|
||||
int reverse = unwrap_args(left, right, self, other);
|
||||
if (reverse == unwrap_exception_code)
|
||||
return -1;
|
||||
|
||||
// call the function
|
||||
PyObject* result =
|
||||
PyEval_CallMethod(self,
|
||||
const_cast<char*>(reverse ? "__rcmp__" : "__cmp__"),
|
||||
const_cast<char*>("(O)"),
|
||||
other);
|
||||
if (result == 0)
|
||||
{
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_TypeError, "bad operand type(s) for cmp() or <");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
return BOOST_PYTHON_CONVERSION::from_python(result, type<int>());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_TypeError, "cmp() didn't return int");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
PyTypeObject operator_dispatcher::type_obj =
|
||||
{
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
const_cast<char*>("operator_dispatcher"),
|
||||
sizeof(operator_dispatcher),
|
||||
0,
|
||||
&operator_dispatcher_dealloc,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&operator_dispatcher_call_cmp,
|
||||
0,
|
||||
&operator_dispatcher::number_methods,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
PyNumberMethods operator_dispatcher::number_methods =
|
||||
{
|
||||
&operator_dispatcher_call_add,
|
||||
&operator_dispatcher_call_sub,
|
||||
&operator_dispatcher_call_mul,
|
||||
&operator_dispatcher_call_div,
|
||||
&operator_dispatcher_call_mod,
|
||||
&operator_dispatcher_call_divmod,
|
||||
&operator_dispatcher_call_pow,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&operator_dispatcher_call_lshift,
|
||||
&operator_dispatcher_call_rshift,
|
||||
&operator_dispatcher_call_and,
|
||||
&operator_dispatcher_call_xor,
|
||||
&operator_dispatcher_call_or,
|
||||
&operator_dispatcher_coerce,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::python
|
||||
179
src/functions.cpp
Normal file
179
src/functions.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// Mar 01 01 Use PyObject_INIT() instead of trying to hand-initialize (David Abrahams)
|
||||
|
||||
#include <boost/python/detail/functions.hpp>
|
||||
#include <boost/python/detail/types.hpp>
|
||||
#include <boost/python/detail/singleton.hpp>
|
||||
#include <boost/python/objects.hpp>
|
||||
#include <boost/python/errors.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
struct function::type_object :
|
||||
singleton<function::type_object, callable<boost::python::detail::type_object<function> > >
|
||||
{
|
||||
type_object() : singleton_base(&PyType_Type) {}
|
||||
};
|
||||
|
||||
|
||||
void function::add_to_namespace(reference<function> new_function, const char* name, PyObject* dict)
|
||||
{
|
||||
dictionary d(ref(dict, ref::increment_count));
|
||||
string key(name);
|
||||
|
||||
ref existing_object = d.get_item(key.reference());
|
||||
if (existing_object.get() == 0)
|
||||
{
|
||||
d[key] = ref(new_function.get(), ref::increment_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (existing_object->ob_type == type_object::instance())
|
||||
{
|
||||
function* f = static_cast<function*>(existing_object.get());
|
||||
while (f->m_overloads.get() != 0)
|
||||
f = f->m_overloads.get();
|
||||
f->m_overloads = new_function;
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetObject(PyExc_RuntimeError,
|
||||
(string("Attempt to overload ") + name
|
||||
+ " failed. The existing attribute has type "
|
||||
+ existing_object->ob_type->tp_name).get());
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function::function()
|
||||
: python_object(type_object::instance())
|
||||
{
|
||||
}
|
||||
|
||||
PyObject* function::call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// Traverse the linked list of function overloads until we find one that
|
||||
// matches.
|
||||
for (const function* f = this; f != 0; f = f->m_overloads.get())
|
||||
{
|
||||
PyErr_Clear();
|
||||
try
|
||||
{
|
||||
PyObject* const result = f->do_call(args, keywords);
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
catch(const argument_error&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, no overloads matched the arguments
|
||||
|
||||
// Allow the single-function error-reporting to take effect unless there was
|
||||
// an overload
|
||||
if (m_overloads.get() == 0)
|
||||
return 0;
|
||||
|
||||
// Synthesize a more-explicit error message
|
||||
PyErr_Clear();
|
||||
string message("No overloaded functions match (");
|
||||
tuple arguments(ref(args, ref::increment_count));
|
||||
for (std::size_t i = 0; i < arguments.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
message += ", ";
|
||||
message += arguments[i]->ob_type->tp_name;
|
||||
}
|
||||
|
||||
message += "). Candidates are:\n";
|
||||
for (const function* f1 = this; f1 != 0; f1 = f1->m_overloads.get())
|
||||
{
|
||||
if (f1 != this)
|
||||
message += "\n";
|
||||
message += f1->description();
|
||||
}
|
||||
|
||||
PyErr_SetObject(PyExc_TypeError, message.get());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The instance class whose obj represents the type of bound_function
|
||||
// objects in Python. bound_functions must be GetAttrable so the __doc__
|
||||
// attribute of built-in Python functions can be accessed when bound.
|
||||
struct bound_function::type_object :
|
||||
singleton<bound_function::type_object,
|
||||
getattrable<callable<boost::python::detail::type_object<bound_function> > > >
|
||||
{
|
||||
type_object() : singleton_base(&PyType_Type) {}
|
||||
|
||||
private: // type_object<bound_function> hook override
|
||||
void dealloc(bound_function*) const;
|
||||
};
|
||||
|
||||
bound_function* bound_function::create(const ref& target, const ref& fn)
|
||||
{
|
||||
bound_function* const result = free_list;
|
||||
if (result == 0)
|
||||
return new bound_function(target, fn);
|
||||
|
||||
free_list = result->m_free_list_link;
|
||||
result->m_target = target;
|
||||
result->m_unbound_function = fn;
|
||||
|
||||
PyObject* self = result;
|
||||
PyObject_INIT(self, type_object::instance());
|
||||
return result;
|
||||
}
|
||||
|
||||
bound_function::bound_function(const ref& target, const ref& fn)
|
||||
: python_object(type_object::instance()),
|
||||
m_target(target),
|
||||
m_unbound_function(fn),
|
||||
m_free_list_link(0)
|
||||
{
|
||||
}
|
||||
|
||||
PyObject*
|
||||
bound_function::call(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// Build a new tuple which prepends the target to the arguments
|
||||
tuple tail_arguments(ref(args, ref::increment_count));
|
||||
ref all_arguments(PyTuple_New(tail_arguments.size() + 1));
|
||||
|
||||
PyTuple_SET_ITEM(all_arguments.get(), 0, m_target.get());
|
||||
Py_INCREF(m_target.get());
|
||||
for (std::size_t i = 0; i < tail_arguments.size(); ++i)
|
||||
{
|
||||
PyTuple_SET_ITEM(all_arguments.get(), i + 1, tail_arguments[i].get());
|
||||
Py_INCREF(tail_arguments[i].get());
|
||||
}
|
||||
|
||||
return PyEval_CallObjectWithKeywords(m_unbound_function.get(), all_arguments.get(), keywords);
|
||||
}
|
||||
|
||||
PyObject* bound_function::getattr(const char* name) const
|
||||
{
|
||||
return PyObject_GetAttrString(m_unbound_function.get(), const_cast<char*>(name));
|
||||
}
|
||||
|
||||
void bound_function::type_object::dealloc(bound_function* obj) const
|
||||
{
|
||||
obj->m_free_list_link = free_list;
|
||||
free_list = obj;
|
||||
obj->m_target.reset();
|
||||
obj->m_unbound_function.reset();
|
||||
}
|
||||
|
||||
bound_function* bound_function::free_list;
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
@@ -1,82 +0,0 @@
|
||||
# (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)
|
||||
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
# (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)
|
||||
|
||||
|
||||
36
src/init_function.cpp
Normal file
36
src/init_function.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#include <boost/python/detail/init_function.hpp>
|
||||
#include <boost/python/objects.hpp>
|
||||
#include <boost/python/detail/extension_class.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
PyObject* init::do_call(PyObject* args_, PyObject* keywords) const
|
||||
{
|
||||
tuple args(ref(args_, ref::increment_count));
|
||||
if (args[0]->ob_type->ob_type != extension_meta_class())
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "argument 1 to __init__ must be an ExtensionInstance");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extension_instance *self = static_cast<extension_instance*>(args[0].get());
|
||||
|
||||
tuple ctor_args = args.slice(1, args.size());
|
||||
|
||||
std::auto_ptr<instance_holder_base> result(
|
||||
create_holder(self, ctor_args.get(), keywords));
|
||||
|
||||
self->add_implementation(result);
|
||||
return none();
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
62
src/module_builder.cpp
Normal file
62
src/module_builder.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
#include <boost/python/module_builder.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace {
|
||||
ref name_holder;
|
||||
}
|
||||
|
||||
bool module_builder::initializing()
|
||||
{
|
||||
return name_holder.get() != 0;
|
||||
}
|
||||
|
||||
string module_builder::name()
|
||||
{
|
||||
// If this fails, you haven't created a module_builder object
|
||||
assert(initializing());
|
||||
return string(name_holder);
|
||||
}
|
||||
|
||||
module_builder::module_builder(const char* name)
|
||||
: m_module(Py_InitModule(const_cast<char*>(name), initial_methods))
|
||||
{
|
||||
// If this fails, you've created more than 1 module_builder object in your module
|
||||
assert(name_holder.get() == 0);
|
||||
name_holder = ref(PyObject_GetAttrString(m_module, const_cast<char*>("__name__")));
|
||||
}
|
||||
|
||||
module_builder::~module_builder()
|
||||
{
|
||||
name_holder.reset();
|
||||
}
|
||||
|
||||
void
|
||||
module_builder::add(detail::function* x, const char* name)
|
||||
{
|
||||
reference<detail::function> f(x); // First take possession of the object.
|
||||
detail::function::add_to_namespace(f, name, PyModule_GetDict(m_module));
|
||||
}
|
||||
|
||||
void module_builder::add(ref x, const char* name)
|
||||
{
|
||||
PyObject* dictionary = PyModule_GetDict(m_module);
|
||||
PyDict_SetItemString(dictionary, const_cast<char*>(name), x.get());
|
||||
}
|
||||
|
||||
void module_builder::add(PyTypeObject* x, const char* name /*= 0*/)
|
||||
{
|
||||
this->add(ref(as_object(x)), name ? name : x->tp_name);
|
||||
}
|
||||
|
||||
PyMethodDef module_builder::initial_methods[] = { { 0, 0, 0, 0 } };
|
||||
|
||||
}} // namespace boost::python
|
||||
@@ -1,117 +0,0 @@
|
||||
// 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
|
||||
@@ -1,95 +0,0 @@
|
||||
// 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
|
||||
485
src/objects.cpp
Normal file
485
src/objects.cpp
Normal file
@@ -0,0 +1,485 @@
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
// TODO: Move inline implementations from objects.cpp here
|
||||
|
||||
#include <boost/python/objects.hpp>
|
||||
#include <boost/python/detail/none.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
T object_from_python(PyObject* p, type<T>)
|
||||
{
|
||||
ref x(p, ref::increment_count);
|
||||
if (!T::accepts(x))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
|
||||
throw error_already_set();
|
||||
}
|
||||
return T(x);
|
||||
}
|
||||
|
||||
inline PyObject* object_to_python(const object& x)
|
||||
{
|
||||
return x.reference().release();
|
||||
}
|
||||
|
||||
object::object(ref p)
|
||||
: m_p(p) {}
|
||||
|
||||
// Return a reference to the held object
|
||||
ref object::reference() const
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
// Return a raw pointer to the held object
|
||||
PyObject* object::get() const
|
||||
{
|
||||
return m_p.get();
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
PyObject* to_python(const boost::python::tuple& x)
|
||||
{
|
||||
return object_to_python(x);
|
||||
}
|
||||
|
||||
boost::python::tuple from_python(PyObject* p, boost::python::type<boost::python::tuple> type)
|
||||
{
|
||||
return boost::python::object_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(const boost::python::list& x)
|
||||
{
|
||||
return object_to_python(x);
|
||||
}
|
||||
|
||||
boost::python::list from_python(PyObject* p, boost::python::type<boost::python::list> type)
|
||||
{
|
||||
return boost::python::object_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(const boost::python::dictionary& x)
|
||||
{
|
||||
return object_to_python(x);
|
||||
}
|
||||
|
||||
boost::python::dictionary from_python(PyObject* p, boost::python::type<boost::python::dictionary> type)
|
||||
{
|
||||
return boost::python::object_from_python(p, type);
|
||||
}
|
||||
|
||||
PyObject* to_python(const boost::python::string& x)
|
||||
{
|
||||
return object_to_python(x);
|
||||
}
|
||||
|
||||
boost::python::string from_python(PyObject* p, boost::python::type<boost::python::string> type)
|
||||
{
|
||||
return boost::python::object_from_python(p, type);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
tuple::tuple(std::size_t n)
|
||||
: object(ref(PyTuple_New(n)))
|
||||
{
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
PyTuple_SET_ITEM(get(), i, detail::none());
|
||||
}
|
||||
|
||||
tuple::tuple(ref p)
|
||||
: object(p)
|
||||
{
|
||||
assert(accepts(p));
|
||||
if (!accepts(p))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
PyTypeObject* tuple::type_obj()
|
||||
{
|
||||
return &PyTuple_Type;
|
||||
}
|
||||
|
||||
bool tuple::accepts(ref p)
|
||||
{
|
||||
return PyTuple_Check(p.get());
|
||||
}
|
||||
|
||||
std::size_t tuple::size() const
|
||||
{
|
||||
return PyTuple_Size(get());
|
||||
}
|
||||
|
||||
ref tuple::operator[](std::size_t pos) const
|
||||
{
|
||||
return ref(PyTuple_GetItem(get(), static_cast<int>(pos)),
|
||||
ref::increment_count);
|
||||
}
|
||||
|
||||
void tuple::set_item(std::size_t pos, const ref& rhs)
|
||||
{
|
||||
int failed = PyTuple_SetItem(
|
||||
get(), static_cast<int>(pos), ref(rhs).release()); // A reference is stolen here.
|
||||
(void)failed;
|
||||
assert(failed == 0);
|
||||
}
|
||||
|
||||
tuple tuple::slice(int low, int high) const
|
||||
{
|
||||
return tuple(ref(PyTuple_GetSlice(get(), low, high)));
|
||||
}
|
||||
|
||||
tuple& tuple::operator+=(const tuple& rhs)
|
||||
{
|
||||
return *this = *this + rhs;
|
||||
}
|
||||
|
||||
|
||||
// Construct from an owned PyObject*.
|
||||
// Precondition: p must point to a python string.
|
||||
string::string(ref p)
|
||||
: object(p)
|
||||
{
|
||||
assert(accepts(p));
|
||||
if (!accepts(p))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
string::string(const char* s)
|
||||
: object(ref(PyString_FromString(s))) {}
|
||||
|
||||
string::string(const char* s, std::size_t length)
|
||||
: object(ref(PyString_FromStringAndSize(s, length))) {}
|
||||
|
||||
string::string(const char* s, interned_t)
|
||||
: object(ref(PyString_InternFromString(s))) {}
|
||||
|
||||
#if 0
|
||||
string::string(const char* s, std::size_t length, interned_t)
|
||||
: object(ref(PyString_InternFromStringAndSize(s, length))) {}
|
||||
#endif
|
||||
|
||||
string::string(const string& rhs)
|
||||
: object(rhs.reference()) {}
|
||||
|
||||
// Get the type object for Strings
|
||||
PyTypeObject* string::type_obj()
|
||||
{ return &PyString_Type; }
|
||||
|
||||
// Return true if the given object is a python string
|
||||
bool string::accepts(ref o)
|
||||
{ return PyString_Check(o.get()); }
|
||||
|
||||
// Return the length of the string.
|
||||
std::size_t string::size() const
|
||||
{
|
||||
int size = PyString_GET_SIZE(get());
|
||||
assert(size >= 0);
|
||||
return static_cast<std::size_t>(size);
|
||||
}
|
||||
|
||||
// Returns a null-terminated representation of the contents of string.
|
||||
// The pointer refers to the internal buffer of string, not a copy.
|
||||
// The data must not be modified in any way. It must not be de-allocated.
|
||||
const char* string::c_str() const
|
||||
{ return PyString_AS_STRING(get()); }
|
||||
|
||||
void string::intern()
|
||||
{ // UNTESTED!!
|
||||
*this = string(ref(PyString_InternFromString(c_str()), ref::increment_count));
|
||||
}
|
||||
|
||||
string& string::operator*=(unsigned int repeat_count)
|
||||
{
|
||||
*this = string(ref(PySequence_Repeat(get(), repeat_count)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
dictionary::dictionary(ref p)
|
||||
: object(p)
|
||||
{
|
||||
assert(accepts(p));
|
||||
if (!accepts(p))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
dictionary::dictionary()
|
||||
: object(ref(PyDict_New())) {}
|
||||
|
||||
PyTypeObject* dictionary::type_obj()
|
||||
{ return &PyDict_Type; }
|
||||
|
||||
bool dictionary::accepts(ref p)
|
||||
{ return PyDict_Check(p.get()); }
|
||||
|
||||
void dictionary::clear()
|
||||
{ PyDict_Clear(get()); }
|
||||
|
||||
const ref& dictionary::proxy::operator=(const ref& rhs)
|
||||
{
|
||||
if (PyDict_SetItem(m_dict.get(), m_key.get(), rhs.get()) == -1)
|
||||
throw error_already_set();
|
||||
return rhs;
|
||||
}
|
||||
|
||||
dictionary::proxy::operator ref() const
|
||||
{
|
||||
return ref(m_dict->ob_type->tp_as_mapping->mp_subscript(m_dict.get(), m_key.get()),
|
||||
ref::increment_count);
|
||||
}
|
||||
|
||||
dictionary::proxy::proxy(const ref& dict, const ref& key)
|
||||
: m_dict(dict), m_key(key) {}
|
||||
|
||||
dictionary::proxy dictionary::operator[](ref key)
|
||||
{ return proxy(reference(), key); }
|
||||
|
||||
ref dictionary::operator[](ref key) const {
|
||||
// An odd MSVC bug causes the ".operator Ptr()" to be needed
|
||||
return proxy(reference(), key).operator ref();
|
||||
}
|
||||
|
||||
|
||||
ref dictionary::get_item(const ref& key) const
|
||||
{
|
||||
return get_item(key, ref());
|
||||
}
|
||||
|
||||
ref dictionary::get_item(const ref& key, const ref& default_) const
|
||||
{
|
||||
PyObject* value_or_null = PyDict_GetItem(get(), key.get());
|
||||
if (value_or_null == 0 && !PyErr_Occurred())
|
||||
return default_;
|
||||
else
|
||||
return ref(value_or_null, ref::increment_count); // Will throw if there was another error
|
||||
}
|
||||
|
||||
void dictionary::set_item(const ref& key, const ref& value)
|
||||
{
|
||||
if (PyDict_SetItem(get(), key.get(), value.get()) == -1)
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
void dictionary::erase(ref key) {
|
||||
if (PyDict_DelItem(get(), key.get()) == -1)
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
list dictionary::items() const { return list(ref(PyDict_Items(get()))); }
|
||||
list dictionary::keys() const { return list(ref(PyDict_Keys(get()))); }
|
||||
list dictionary::values() const { return list(ref(PyDict_Values(get()))); }
|
||||
|
||||
std::size_t dictionary::size() const { return static_cast<std::size_t>(PyDict_Size(get())); }
|
||||
|
||||
string operator+(string x, string y)
|
||||
{
|
||||
PyObject* io_string = x.reference().release();
|
||||
PyString_Concat(&io_string, y.get());
|
||||
return string(ref(io_string));
|
||||
}
|
||||
|
||||
string& string::operator+=(const string& rhs)
|
||||
{
|
||||
return *this = *this + rhs;
|
||||
}
|
||||
|
||||
string& string::operator+=(const char* y)
|
||||
{
|
||||
return *this += string(y);
|
||||
}
|
||||
|
||||
string operator%(const string& format, const tuple& args)
|
||||
{
|
||||
return string(ref(PyString_Format(format.get(), args.reference().get())));
|
||||
}
|
||||
|
||||
string operator+(string x, const char* y)
|
||||
{
|
||||
return x + string(y);
|
||||
}
|
||||
|
||||
string operator+(const char* x, string y)
|
||||
{
|
||||
return string(x) + y;
|
||||
}
|
||||
|
||||
tuple operator+(const tuple& x, const tuple& y)
|
||||
{
|
||||
tuple result(x.size() + y.size());
|
||||
for (std::size_t xi = 0; xi < x.size(); ++xi)
|
||||
result.set_item(xi, x[xi]);
|
||||
for (std::size_t yi = 0; yi < y.size(); ++yi)
|
||||
result.set_item(yi + x.size(), y[yi]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
list::list(ref p)
|
||||
: object(p)
|
||||
{
|
||||
assert(accepts(p));
|
||||
if (!accepts(p))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, p->ob_type->tp_name);
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
list::list(std::size_t sz)
|
||||
: object(ref(PyList_New(sz)))
|
||||
{
|
||||
}
|
||||
|
||||
PyTypeObject* list::type_obj()
|
||||
{
|
||||
return &PyList_Type;
|
||||
}
|
||||
|
||||
bool list::accepts(ref p)
|
||||
{
|
||||
return PyList_Check(p.get());
|
||||
}
|
||||
|
||||
std::size_t list::size() const
|
||||
{
|
||||
return PyList_Size(get());
|
||||
}
|
||||
|
||||
ref list::operator[](std::size_t pos) const
|
||||
{
|
||||
return ref(PyList_GetItem(get(), pos), ref::increment_count);
|
||||
}
|
||||
|
||||
list::proxy list::operator[](std::size_t pos)
|
||||
{
|
||||
return proxy(reference(), pos);
|
||||
}
|
||||
|
||||
void list::insert(std::size_t index, const ref& item)
|
||||
{
|
||||
if (PyList_Insert(get(), index, item.get()) == -1)
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
void list::push_back(const ref& item)
|
||||
{
|
||||
if (PyList_Append(get(), item.get()) == -1)
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
void list::append(const ref& item)
|
||||
{
|
||||
this->push_back(item);
|
||||
}
|
||||
|
||||
list list::slice(int low, int high) const
|
||||
{
|
||||
return list(ref(PyList_GetSlice(get(), low, high)));
|
||||
}
|
||||
|
||||
list::slice_proxy list::slice(int low, int high)
|
||||
{
|
||||
return slice_proxy(reference(), low, high);
|
||||
}
|
||||
|
||||
void list::sort()
|
||||
{
|
||||
if (PyList_Sort(get()) == -1)
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
void list::reverse()
|
||||
{
|
||||
if (PyList_Reverse(get()) == -1)
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
tuple list::as_tuple() const
|
||||
{
|
||||
return tuple(ref(PyList_AsTuple(get())));
|
||||
}
|
||||
|
||||
const ref& list::proxy::operator=(const ref& rhs)
|
||||
{
|
||||
m_list.set_item(m_index, rhs);
|
||||
return rhs;
|
||||
}
|
||||
|
||||
list::proxy::operator ref() const
|
||||
{
|
||||
return ref(PyList_GetItem(m_list.get(), m_index), ref::increment_count);
|
||||
}
|
||||
|
||||
ref list::get_item(std::size_t pos) const
|
||||
{
|
||||
return ref(PyList_GetItem(this->get(), pos), ref::increment_count);
|
||||
}
|
||||
|
||||
void list::set_item(std::size_t pos, const ref& rhs)
|
||||
{
|
||||
int result = PyList_SetItem(this->get(), pos, rhs.get());
|
||||
if (result == -1)
|
||||
throw error_already_set();
|
||||
Py_INCREF(rhs.get());
|
||||
}
|
||||
|
||||
list::proxy::proxy(const ref& list, std::size_t index)
|
||||
: m_list(list), m_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
const list& list::slice_proxy::operator=(const list& rhs)
|
||||
{
|
||||
if (PyList_SetSlice(m_list.get(), m_low, m_high, rhs.get()) == -1)
|
||||
throw error_already_set();
|
||||
return rhs;
|
||||
}
|
||||
|
||||
list::slice_proxy::operator ref() const
|
||||
{
|
||||
return ref(PyList_GetSlice(m_list.get(), m_low, m_high));
|
||||
}
|
||||
|
||||
list::slice_proxy::operator list() const
|
||||
{
|
||||
return list(this->operator ref());
|
||||
}
|
||||
|
||||
std::size_t list::slice_proxy::size() const
|
||||
{
|
||||
return this->operator list().size();
|
||||
}
|
||||
|
||||
ref list::slice_proxy::operator[](std::size_t pos) const
|
||||
{
|
||||
return this->operator list()[pos].operator ref();
|
||||
}
|
||||
|
||||
list::slice_proxy::slice_proxy(const ref& list, int low, int high)
|
||||
: m_list(list), m_low(low), m_high(high)
|
||||
{
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
1347
src/types.cpp
Normal file
1347
src/types.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,39 +0,0 @@
|
||||
// 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
286
test/m1.cpp
@@ -1,286 +0,0 @@
|
||||
// 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
197
test/m2.cpp
@@ -1,197 +0,0 @@
|
||||
// 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"
|
||||
@@ -1,39 +0,0 @@
|
||||
// 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
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
"""
|
||||
>>> 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])
|
||||
@@ -1,14 +0,0 @@
|
||||
// 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