mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
40 Commits
boost-1.36
...
boost-1.30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9529ad16e9 | ||
|
|
955f716108 | ||
|
|
9178b9e6cc | ||
|
|
6f0b083a51 | ||
|
|
574e6b9e2c | ||
|
|
5bfc1e080d | ||
|
|
d475fcaf7d | ||
|
|
85f324efb6 | ||
|
|
08254b1fe7 | ||
|
|
d4b1b46e63 | ||
|
|
08f07b0cc6 | ||
|
|
2d0e0759c7 | ||
|
|
130de54f23 | ||
|
|
3068b4ae13 | ||
|
|
5867b87b60 | ||
|
|
87953ae423 | ||
|
|
eb252c0395 | ||
|
|
2c0ec733ca | ||
|
|
13df532aca | ||
|
|
c8747f6893 | ||
|
|
69b9094dfc | ||
|
|
5788cc83f3 | ||
|
|
0262c3bba9 | ||
|
|
d6dd4e48e2 | ||
|
|
b58503707f | ||
|
|
8c1a826ce8 | ||
|
|
cc76f068ee | ||
|
|
4efab432ab | ||
|
|
13b1f434ad | ||
|
|
c29241d859 | ||
|
|
fbe3d080e8 | ||
|
|
be96a3c4d6 | ||
|
|
70a967bac5 | ||
|
|
a7ce37effa | ||
|
|
87c92775c9 | ||
|
|
a15f7d5bf3 | ||
|
|
a870ce20fc | ||
|
|
e042228f45 | ||
|
|
7c4cfe0589 | ||
|
|
e24497a6cd |
1117
doc/PyConDC_2003/bpl.html
Executable file
1117
doc/PyConDC_2003/bpl.html
Executable file
File diff suppressed because it is too large
Load Diff
BIN
doc/PyConDC_2003/bpl.pdf
Executable file
BIN
doc/PyConDC_2003/bpl.pdf
Executable file
Binary file not shown.
@@ -9,12 +9,10 @@
|
||||
|
||||
:Author: Ralf W. Grosse-Kunstleve
|
||||
|
||||
:status: Draft
|
||||
:copyright: Copyright David Abrahams and Ralf W. Grosse-Kunstleve 2003. All rights reserved
|
||||
|
||||
.. contents:: Table of Contents
|
||||
|
||||
|
||||
.. _`Boost Consulting`: http://www.boost-consulting.com
|
||||
|
||||
==========
|
||||
@@ -631,19 +629,22 @@ virtual functions. At least one very promising project has been
|
||||
started to write a front-end which can generate these dispatchers (and
|
||||
other wrapping code) automatically from C++ headers.
|
||||
|
||||
Pyste builds on GCC_XML_, which generates an XML version of GCC's
|
||||
internal program representation. Since GCC is a highly-conformant C++
|
||||
compiler, this ensures correct handling of the most-sophisticated
|
||||
template code and full access to the underlying type system. In
|
||||
keeping with the Boost.Python philosophy, a Pyste interface
|
||||
description is neither intrusive on the code being wrapped, nor
|
||||
expressed in some unfamiliar language: instead it is a 100% pure
|
||||
Python script. If Pyste is successful it will mark a move away from
|
||||
wrapping everything directly in C++ for many of our users. We expect
|
||||
that soon, not only our users but the Boost.Python developers
|
||||
themselves will be "thinking hybrid" about their own code.
|
||||
Pyste_ is being developed by Bruno da Silva de Oliveira. It builds on
|
||||
GCC_XML_, which generates an XML version of GCC's internal program
|
||||
representation. Since GCC is a highly-conformant C++ compiler, this
|
||||
ensures correct handling of the most-sophisticated template code and
|
||||
full access to the underlying type system. In keeping with the
|
||||
Boost.Python philosophy, a Pyste interface description is neither
|
||||
intrusive on the code being wrapped, nor expressed in some unfamiliar
|
||||
language: instead it is a 100% pure Python script. If Pyste is
|
||||
successful it will mark a move away from wrapping everything directly
|
||||
in C++ for many of our users. It will also allow us the choice to
|
||||
shift some of the metaprogram code from C++ to Python. We expect that
|
||||
soon, not only our users but the Boost.Python developers themselves
|
||||
will be "thinking hybrid" about their own code.
|
||||
|
||||
.. _`GCC_XML`: http://www.gccxml.org/HTML/Index.html
|
||||
.. _`Pyste`: http://www.boost.org/libs/python/pyste
|
||||
|
||||
---------------
|
||||
Serialization
|
||||
@@ -770,15 +771,6 @@ This almost looks and works like regular Python code, but it is pure
|
||||
C++. Of course we can wrap C++ functions which accept or return
|
||||
``object`` instances.
|
||||
|
||||
.. =====================
|
||||
Development history
|
||||
=====================
|
||||
|
||||
XXX Outline of development history to illustrate that the
|
||||
library is mature. XXX
|
||||
|
||||
This can be postponed for the PyConDC paper
|
||||
|
||||
=================
|
||||
Thinking hybrid
|
||||
=================
|
||||
@@ -816,7 +808,7 @@ mainly concentrated on the C++ parts. However, as the toolbox is
|
||||
becoming more complete, more and more newly added functionality can be
|
||||
implemented in Python.
|
||||
|
||||
.. image:: python_cpp_mix.png
|
||||
.. image:: python_cpp_mix.jpg
|
||||
|
||||
This figure shows the estimated ratio of newly added C++ and Python
|
||||
code over time as new algorithms are implemented. We expect this
|
||||
@@ -826,6 +818,87 @@ language is the return on our investment in Boost.Python. The ability
|
||||
to access all of our code from Python allows a broader group of
|
||||
developers to use it in the rapid development of new applications.
|
||||
|
||||
=====================
|
||||
Development history
|
||||
=====================
|
||||
|
||||
The first version of Boost.Python was developed in 2000 by Dave
|
||||
Abrahams at Dragon Systems, where he was privileged to have Tim Peters
|
||||
as a guide to "The Zen of Python". One of Dave's jobs was to develop
|
||||
a Python-based natural language processing system. Since it was
|
||||
eventually going to be targeting embedded hardware, it was always
|
||||
assumed that the compute-intensive core would be rewritten in C++ to
|
||||
optimize speed and memory footprint [#1]_. The project also wanted to
|
||||
test all of its C++ code using Python test scripts [#2]_. The only
|
||||
tool we knew of for binding C++ and Python was SWIG_, and at the time
|
||||
its handling of C++ was weak. It would be false to claim any deep
|
||||
insight into the possible advantages of Boost.Python's approach at
|
||||
this point. Dave's interest and expertise in fancy C++ template
|
||||
tricks had just reached the point where he could do some real damage,
|
||||
and Boost.Python emerged as it did because it filled a need and
|
||||
because it seemed like a cool thing to try.
|
||||
|
||||
This early version was aimed at many of the same basic goals we've
|
||||
described in this paper, differing most-noticeably by having a
|
||||
slightly more cumbersome syntax and by lack of special support for
|
||||
operator overloading, pickling, and component-based development.
|
||||
These last three features were quickly added by Ullrich Koethe and
|
||||
Ralf Grosse-Kunstleve [#3]_, and other enthusiastic contributors arrived
|
||||
on the scene to contribute enhancements like support for nested
|
||||
modules and static member functions.
|
||||
|
||||
By early 2001 development had stabilized and few new features were
|
||||
being added, however a disturbing new fact came to light: Ralf had
|
||||
begun testing Boost.Python on pre-release versions of a compiler using
|
||||
the EDG_ front-end, and the mechanism at the core of Boost.Python
|
||||
responsible for handling conversions between Python and C++ types was
|
||||
failing to compile. As it turned out, we had been exploiting a very
|
||||
common bug in the implementation of all the C++ compilers we had
|
||||
tested. We knew that as C++ compilers rapidly became more
|
||||
standards-compliant, the library would begin failing on more
|
||||
platforms. Unfortunately, because the mechanism was so central to the
|
||||
functioning of the library, fixing the problem looked very difficult.
|
||||
|
||||
Fortunately, later that year Lawrence Berkeley and later Lawrence
|
||||
Livermore National labs contracted with `Boost Consulting`_ for support
|
||||
and development of Boost.Python, and there was a new opportunity to
|
||||
address fundamental issues and ensure a future for the library. A
|
||||
redesign effort began with the low level type conversion architecture,
|
||||
building in standards-compliance and support for component-based
|
||||
development (in contrast to version 1 where conversions had to be
|
||||
explicitly imported and exported across module boundaries). A new
|
||||
analysis of the relationship between the Python and C++ objects was
|
||||
done, resulting in more intuitive handling for C++ lvalues and
|
||||
rvalues.
|
||||
|
||||
The emergence of a powerful new type system in Python 2.2 made the
|
||||
choice of whether to maintain compatibility with Python 1.5.2 easy:
|
||||
the opportunity to throw away a great deal of elaborate code for
|
||||
emulating classic Python classes alone was too good to pass up. In
|
||||
addition, Python iterators and descriptors provided crucial and
|
||||
elegant tools for representing similar C++ constructs. The
|
||||
development of the generalized ``object`` interface allowed us to
|
||||
further shield C++ programmers from the dangers and syntactic burdens
|
||||
of the Python 'C' API. A great number of other features including C++
|
||||
exception translation, improved support for overloaded functions, and
|
||||
most significantly, CallPolicies for handling pointers and
|
||||
references, were added during this period.
|
||||
|
||||
In October 2002, version 2 of Boost.Python was released. Development
|
||||
since then has concentrated on improved support for C++ runtime
|
||||
polymorphism and smart pointers. Peter Dimov's ingenious
|
||||
``boost::shared_ptr`` design in particular has allowed us to give the
|
||||
hybrid developer a consistent interface for moving objects back and
|
||||
forth across the language barrier without loss of information. At
|
||||
first, we were concerned that the sophistication and complexity of the
|
||||
Boost.Python v2 implementation might discourage contributors, but the
|
||||
emergence of Pyste_ and several other significant feature
|
||||
contributions have laid those fears to rest. Daily questions on the
|
||||
Python C++-sig and a backlog of desired improvements show that the
|
||||
library is getting used. To us, the future looks bright.
|
||||
|
||||
.. _`EDG`: http://www.edg.com
|
||||
|
||||
=============
|
||||
Conclusions
|
||||
=============
|
||||
@@ -844,10 +917,21 @@ like serialization that are trivial in Python can be very difficult in
|
||||
pure C++. Given the luxury of building a hybrid software system from
|
||||
the ground up, we can approach design with new confidence and power.
|
||||
|
||||
===========
|
||||
Citations
|
||||
===========
|
||||
|
||||
.. [VELD1995] T. Veldhuizen, "Expression Templates," C++ Report,
|
||||
Vol. 7 No. 5 June 1995, pp. 26-31.
|
||||
http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
|
||||
|
||||
.. [#1] In retrospect, it seems that "thinking hybrid" from the ground up
|
||||
might have been better for the NLP system: the natural component
|
||||
boundaries defined by the pure python prototype turned out to be
|
||||
inappropriate for getting the desired performance and memory footprint
|
||||
out of the C++ core, which eventually caused some redesign overhead on
|
||||
the Python side when the core was moved to C++.
|
||||
|
||||
.. [#2] We also have some reservations about driving all C++ testing through a
|
||||
Python interface, unless that's the only way it will be ultimately
|
||||
used. Any transition across language boundaries with such different
|
||||
object models can inevitably mask bugs.
|
||||
|
||||
.. [#3] These features were expressed very differently in v1 of
|
||||
Boost.Python
|
||||
|
||||
BIN
doc/PyConDC_2003/python_cpp_mix.jpg
Executable file
BIN
doc/PyConDC_2003/python_cpp_mix.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -357,7 +357,7 @@ bjam -sTOOLS=<i><a href=
|
||||
(i.e. <code>c:/Python/Libs</code>. Make sure it is <code>Libs</code> with
|
||||
an "<code>s</code>" and not just <code>Lib</code>).</p>
|
||||
|
||||
<h3>Using the IDE for you own projects</h3>
|
||||
<h3>Using the IDE for your own projects</h3>
|
||||
|
||||
<p>Building your own projects using the IDE is slightly more complicated.
|
||||
Firstly, you need to make sure that the project you create as the right
|
||||
|
||||
@@ -31,6 +31,15 @@
|
||||
<p><a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a> is
|
||||
the architect, designer, and implementor of <b>Boost.Python</b>.</p>
|
||||
|
||||
<p><a href="mailto:brett.calcott@paradise.net.nz">Brett Calcott</a>
|
||||
contributed and maintains the Visual Studio project files and
|
||||
documentation.</p>
|
||||
|
||||
<p><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
|
||||
Ganßauge</a> supplied support for opaque pointer conversions,
|
||||
complete with documentation and a regression test (and I didn't
|
||||
even have to ask him for those)!
|
||||
|
||||
<p>Joel de Guzman implemented the <a href="overloads.html">default
|
||||
argument support</a> and wrote the excellent <a href=
|
||||
"../tutorial/index.html">tutorial documentation</a>.</p>
|
||||
@@ -63,6 +72,17 @@
|
||||
use the new preproccessor metaprogramming constructs and helping us to
|
||||
work around buggy and slow C++ preprocessors.</p>
|
||||
|
||||
<p><a href="nicodemus-at-globalite.com.br">Bruno da Silva de
|
||||
Oliveira</a> contributed the ingenious <a
|
||||
href="../../pyste/index.html">Pyste</a> ("Pie-Steh")
|
||||
code generator.
|
||||
|
||||
<p><a href="mailto:nickm@sitius.com">Nikolay Mladenov</a> contributed
|
||||
<code>staticmethod</code> support.</p>
|
||||
|
||||
<p>Martin Casado solved some sticky problems which allow us to build the
|
||||
Boost.Python shared library for AIX's crazy dynamic linking model.</p>
|
||||
|
||||
<p><a href="mailto:achim@procoders.net">Achim Domma</a> contributed some
|
||||
of the <a href="reference.html#object_wrappers">Object Wrappers</a> and
|
||||
HTML templates for this documentation. Dave Hawkes contributed
|
||||
@@ -71,16 +91,6 @@
|
||||
definition syntax. Pearu Pearson wrote some of the test cases that are in
|
||||
the current test suite.</p>
|
||||
|
||||
<p><a href="mailto:brett.calcott@paradise.net.nz">Brett Calcott</a>
|
||||
contributed and maintains the Visual Studio project files and
|
||||
documentation.</p>
|
||||
|
||||
<p><a href="mailto:nickm@sitius.com">Nikolay Mladenov</a> contributed
|
||||
<code>staticmethod</code> support.</p>
|
||||
|
||||
<p>Martin Casado solved some sticky problems which allow us to build the
|
||||
Boost.Python shared library for AIX's crazy dynamic linking model.</p>
|
||||
|
||||
<p>The development of this version of Boost.Python was funded in part by
|
||||
the <a href="http://www.llnl.gov/">Lawrence Livermore National
|
||||
Laboratories</a> and by the <a href="http://cci.lbl.gov/">Computational
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
|
||||
<dt><a href="#funcptr">How can I wrap a function which takes a
|
||||
function pointer as an argument?</a><dd>
|
||||
|
||||
<dt><a href="#dangling">I'm getting the "attempt to return dangling
|
||||
reference" error. What am I doing wrong?</a></dt>
|
||||
|
||||
@@ -56,6 +60,57 @@
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="funcptr">How can I wrap a function which takes a
|
||||
function pointer as an argument?</a></h2>
|
||||
|
||||
If what you're trying to do is something like this:
|
||||
<pre>
|
||||
typedef boost::function<void (string s) > funcptr;
|
||||
|
||||
void foo(funcptr fp)
|
||||
{
|
||||
fp("hello,world!");
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(test)
|
||||
{
|
||||
def("foo",foo) ;
|
||||
}
|
||||
</pre>
|
||||
|
||||
And then:
|
||||
|
||||
<pre>
|
||||
>>> def hello(s):
|
||||
... print s
|
||||
...
|
||||
>>> foo(hello)
|
||||
hello, world!
|
||||
</pre>
|
||||
|
||||
The short answer is: "you can't". This is not a
|
||||
Boost.Python limitation so much as a limitation of C++. The
|
||||
problem is that a Python function is actually data, and the only
|
||||
way of associating data with a C++ function pointer is to store it
|
||||
in a static variable of the function. The problem with that is
|
||||
that you can only associate one piece of data with every C++
|
||||
function, and we have no way of compiling a new C++ function
|
||||
on-the-fly for every Python function you decide to pass
|
||||
to <code>foo</code>. In other words, this could work if the C++
|
||||
function is always going to invoke the <em>same</em> Python
|
||||
function, but you probably don't want that.
|
||||
|
||||
<p>If you have the luxury of changing the C++ code you're
|
||||
wrapping, pass it an <code>object</code> instead and call that;
|
||||
the overloaded function call operator will invoke the Python
|
||||
function you pass it behind the <code>object</code>.
|
||||
|
||||
<p>For more perspective on the issue, see <a
|
||||
href="http://aspn.activestate.com/ASPN/Mail/Message/1554837">this
|
||||
posting</a>.
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="dangling">I'm getting the "attempt to return dangling
|
||||
reference" error. What am I doing wrong?</a></h2>
|
||||
That exception is protecting you from causing a nasty crash. It usually
|
||||
@@ -492,7 +547,7 @@ void b_insert(B& b, std::auto_ptr<A> a)
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
23 January, 2003
|
||||
18 March, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
|
||||
142
doc/v2/opaque_pointer_converter.html
Normal file
142
doc/v2/opaque_pointer_converter.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/opaque_pointer_converter.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/opaque_pointer_converter.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque_pointer_converter-spec">Class template
|
||||
<code>opaque_pointer_converter<P></code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque_pointer_converter-spec-synopsis">Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">Macro
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
|
||||
<dt><a href="#see-also">See Also</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="opaque_pointer_converter-spec"></a>Class template
|
||||
<code>opaque_pointer_converter<P></code></h3>
|
||||
|
||||
<p><code>opaque_pointer_converter<></code> is derived from
|
||||
<a href="to_python_converter.html#to_python_converter-spec">
|
||||
<code>to_python_converter</code></a>
|
||||
and registers itself as an
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into pointers to undefined types.
|
||||
Thus it may be used as a converter from opaque pointers into
|
||||
Python objects and vice versa.</p>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-synopsis"></a>Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template<class Pointer>
|
||||
struct opaque_pointer_converter
|
||||
: to_python_converter<
|
||||
Pointer, opaque_pointer_converter<Pointer> >
|
||||
{
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-constructor"></a>Class template
|
||||
<code>opaque_pointer_converter</code> constructor</h4>
|
||||
<pre>
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<p>Registers the instance as a
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into opaque pointers.</p>
|
||||
<p>The name is used for the type of the Python Objects created;
|
||||
it should be printable but needn't be an
|
||||
<a href="definitions.html#ntbs">ntbs</a> because the object type is
|
||||
not supposed to be user constructible within python scripts.</p>
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="macros"></a>Macros</h2>
|
||||
|
||||
<h3><a name="BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec"></a>
|
||||
Macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)</h3>
|
||||
<p>This macro must be used to define specializations of the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
which can't be instantiated for incomplete types.</p>
|
||||
<h4>Note</h4>
|
||||
<p>In order for this to work in a cross-module environment the macro must
|
||||
be invoked in every translation unit which uses the
|
||||
opaque_pointer_converter.</p>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
please see example for <a href="return_opaque_pointer.html#example">
|
||||
return_opaque_pointer</a>.
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="return_opaque_pointer.html">return_opaque_pointer</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
10 March, 2003
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright 2003 Haufe Mediengruppe. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/raw_function.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header <boost/python/raw_function.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#raw_function-spec">raw_function</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p><code><a href="#raw_function-spec">raw_function</a>(...)</code>
|
||||
is used to convert a function taking a <a
|
||||
href="tuple.html#tuple-spec">tuple</a> and a <a
|
||||
href="dict.html#dict-spec">dict</a> into a Python callable object
|
||||
which accepts a variable number of arguments and arbitrary keyword
|
||||
arguments.
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<a name="raw_function-spec"></a>raw_function
|
||||
<pre>
|
||||
template <class F>
|
||||
object raw_function(F f, std::size_t min_args = 0);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>f(tuple(), dict())</code> is
|
||||
well-formed.</dt>
|
||||
|
||||
<dt><b>Returns:</b> a <a href=
|
||||
"http://www.python.org/doc/current/lib/built-in-funcs.html#l2h-6">callable</a> object which requires at least <code>min_args</code> arguments. When called, the actual non-keyword arguments will be passed in a <a
|
||||
href="tuple.html#tuple-spec">tuple</a> as the first argument to <code>f</code>, and the keyword arguments will be passed in a <a
|
||||
href="dict.html#dict-spec">dict</a> as the second argument to <code>f</code>.
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
C++:
|
||||
<pre>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/dict.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/raw_function.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
tuple raw(tuple args, dict kw)
|
||||
{
|
||||
return make_tuple(args, kw);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(raw_test)
|
||||
{
|
||||
def("raw", raw_function(raw));
|
||||
}
|
||||
</pre>
|
||||
|
||||
Python:
|
||||
<pre>
|
||||
>>> from raw_test import *
|
||||
|
||||
>>> raw(3, 4, foo = 'bar', baz = 42)
|
||||
((3, 4), {'foo': 'bar', 'baz': 42})
|
||||
</pre>
|
||||
<p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
7 March, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -749,6 +749,22 @@
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="return_opaque_pointer.html">return_opaque_pointer.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="return_opaque_pointer.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="return_opaque_pointer.html#return_opaque_pointer-spec">
|
||||
return_opaque_pointer</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -806,6 +822,29 @@
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="opaque_pointer_converter.html">opaque_pointer_converter.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="opaque_pointer_converter.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="opaque_pointer_converter.html#opaque_pointer_converter-spec">
|
||||
opaque_pointer_converter</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="opaque_pointer_converter.html#macros">Macros</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="opaque_pointer_converter.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="to_python_converter.html">to_python_converter.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
|
||||
189
doc/v2/return_opaque_pointer.html
Normal file
189
doc/v2/return_opaque_pointer.html
Normal file
@@ -0,0 +1,189 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/return_opaque_pointer.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/return_opaque_pointer.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#return_opaque_pointer-spec">Class
|
||||
<code>return_opaque_pointer</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#return_opaque_pointer-spec-synopsis">Class
|
||||
<code>return_opaque_pointer</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#return_opaque_pointer-spec-metafunctions">Class
|
||||
<code>return_opaque_pointer</code> metafunctions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
|
||||
<dt><a href="#see-also">See Also</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="return_opaque_pointer-spec"></a>Class
|
||||
<code>return_opaque_pointer</code></h3>
|
||||
|
||||
<p><code>return_opaque_pointer</code> is a model of
|
||||
<a href="ResultConverter.html#ResultConverterGenerator-concept">
|
||||
ResultConverterGenerator</a>
|
||||
which can be used to wrap C++ functions returning pointers to
|
||||
undefined types such that the return value is copied into a
|
||||
new Python object.</p>
|
||||
<p>In addition to specifying the <code>return_opaque_pointer</code>
|
||||
policy the <a href="opaque_pointer_converter.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a> macro must be
|
||||
used to define specializations for the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
on the type pointed to by returned pointer.</p>
|
||||
|
||||
<h4><a name="return_opaque_pointer-spec-synopsis"></a>Class
|
||||
<code>return_opaque_pointer</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
struct return_opaque_pointer
|
||||
{
|
||||
template <class R> struct apply;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="return_opaque_pointer-spec-metafunctions"></a>Class
|
||||
<code>return_opaque_pointer</code> metafunctions</h4>
|
||||
<pre>
|
||||
template <class R> struct apply
|
||||
</pre>
|
||||
|
||||
<dl class="metafunction-semantics">
|
||||
<dt><b>Returns:</b> <code>typedef
|
||||
detail::opaque_conversion_holder<R>
|
||||
type;</code></dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<h3>C++ Module Definition</h3>
|
||||
<pre>
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/def.hpp>
|
||||
# include <boost/python/module.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
|
||||
typedef struct opaque_ *opaque;
|
||||
|
||||
opaque the_op = ((opaque) 0x47110815);
|
||||
|
||||
opaque get () { return the_op; }
|
||||
void use (opaque op) {
|
||||
if (op != the_op)
|
||||
throw std::runtime_error (std::string ("failed"));
|
||||
}
|
||||
|
||||
void failuse (opaque op) {
|
||||
if (op == the_op)
|
||||
throw std::runtime_error (std::string ("success"));
|
||||
}
|
||||
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
|
||||
|
||||
namespace bpl = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE(opaque_ext)
|
||||
{
|
||||
bpl::def (
|
||||
"get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
|
||||
bpl::def ("use", &::use);
|
||||
bpl::def ("failuse", &::failuse);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Python Code</h3>
|
||||
<pre>
|
||||
"""
|
||||
>>> from opaque_ext import *
|
||||
>>> #
|
||||
>>> # Check for correct conversion
|
||||
>>> use(get())
|
||||
>>> failuse(get())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
RuntimeError: success
|
||||
>>> #
|
||||
>>> # Check that there is no conversion from integers ...
|
||||
>>> use(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # ... and from strings to opaque objects
|
||||
>>> use("")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
"""
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
</pre>
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="opaque_pointer_converter.html">
|
||||
opaque_pointer_converter</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
28 January, 2003
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright 2003 Haufe Mediengruppe. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -44,12 +44,14 @@
|
||||
# include <boost/python/object_protocol.hpp>
|
||||
# include <boost/python/object_protocol_core.hpp>
|
||||
# include <boost/python/operators.hpp>
|
||||
# include <boost/python/opaque_pointer_converter.hpp>
|
||||
# include <boost/python/other.hpp>
|
||||
# include <boost/python/overloads.hpp>
|
||||
# include <boost/python/pointee.hpp>
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/reference_existing_object.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/scope.hpp>
|
||||
# include <boost/python/self.hpp>
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#ifndef CONFIG_DWA052200_H_
|
||||
# define CONFIG_DWA052200_H_
|
||||
|
||||
#if defined(__ALPHA) && defined(__osf__) && defined(__DECCXX_VER)
|
||||
# include <pyconfig.h>
|
||||
#endif
|
||||
# include <boost/config.hpp>
|
||||
|
||||
# ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
18
include/boost/python/detail/dealloc.hpp
Normal file
18
include/boost/python/detail/dealloc.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright Gottfried Ganßauge 2003. 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 BOOST_PYTHON_DETAIL_DEALLOC_HPP_
|
||||
# define BOOST_PYTHON_DETAIL_DEALLOC_HPP_
|
||||
namespace boost { namespace python { namespace detail {
|
||||
extern "C"
|
||||
{
|
||||
inline void dealloc(PyObject* self)
|
||||
{
|
||||
PyObject_Del(self);
|
||||
}
|
||||
}
|
||||
}}} // namespace boost::python::detail
|
||||
# endif // BOOST_PYTHON_DETAIL_DEALLOC_HPP_
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright David Abrahams 2003. 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 IS_SHARED_PTR_DWA2003224_HPP
|
||||
# define IS_SHARED_PTR_DWA2003224_HPP
|
||||
|
||||
# include <boost/python/detail/is_xxx.hpp>
|
||||
# include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
BOOST_PYTHON_IS_XXX_DEF(shared_ptr, shared_ptr, 1)
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // IS_SHARED_PTR_DWA2003224_HPP
|
||||
@@ -24,6 +24,9 @@
|
||||
// Python's LongObject.h helpfully #defines ULONGLONG_MAX for us,
|
||||
// which confuses Boost's config
|
||||
//
|
||||
#if defined(__ALPHA) && defined(__osf__) && defined(__DECCXX_VER)
|
||||
# include <pyconfig.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#ifndef ULONG_MAX
|
||||
# define BOOST_PYTHON_ULONG_MAX_UNDEFINED
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
#ifndef HAS_BACK_REFERENCE_DWA2002323_HPP
|
||||
# define HAS_BACK_REFERENCE_DWA2002323_HPP
|
||||
|
||||
#if defined(__ALPHA) && defined(__osf__) && defined(__DECCXX_VER)
|
||||
# include <pyconfig.h>
|
||||
#endif
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// traits class which users can specialize to indicate that a class
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#ifndef OBJECT_CORE_DWA2002615_HPP
|
||||
# define OBJECT_CORE_DWA2002615_HPP
|
||||
|
||||
#if defined(__ALPHA) && defined(__osf__) && defined(__DECCXX_VER)
|
||||
# include <pyconfig.h>
|
||||
#endif
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/call.hpp>
|
||||
|
||||
145
include/boost/python/opaque_pointer_converter.hpp
Normal file
145
include/boost/python/opaque_pointer_converter.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright Gottfried Ganßauge 2003. 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.
|
||||
/*
|
||||
* Generic Conversion of opaque C++-pointers to a Python-Wrapper.
|
||||
*/
|
||||
# ifndef OPAQUE_POINTER_CONVERTER_HPP_
|
||||
# define OPAQUE_POINTER_CONVERTER_HPP_
|
||||
# include <boost/python/lvalue_from_pytype.hpp>
|
||||
# include <boost/python/to_python_converter.hpp>
|
||||
# include <boost/python/detail/dealloc.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/type_traits/remove_pointer.hpp>
|
||||
|
||||
// opaque_pointer_converter --
|
||||
//
|
||||
// usage: opaque_pointer_converter<Pointer>("name")
|
||||
//
|
||||
// registers to- and from- python conversions for a type Pointer,
|
||||
// and a corresponding Python type called "name".
|
||||
//
|
||||
// Note:
|
||||
// In addition you need to define specializations for type_id
|
||||
// on the type pointed to by Pointer using
|
||||
// BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
|
||||
//
|
||||
// For an example see libs/python/test/opaque.cpp
|
||||
//
|
||||
namespace boost { namespace python {
|
||||
namespace detail {
|
||||
template <class R>
|
||||
struct opaque_pointer_converter_requires_a_pointer_type
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
|
||||
{}
|
||||
# endif
|
||||
;
|
||||
}
|
||||
|
||||
template <class Pointer>
|
||||
struct opaque_pointer_converter
|
||||
: to_python_converter<
|
||||
Pointer, opaque_pointer_converter<Pointer> >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ok = is_pointer<Pointer>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
ok
|
||||
, Pointer
|
||||
, detail::opaque_pointer_converter_requires_a_pointer_type<Pointer>
|
||||
>::type ptr_type;
|
||||
|
||||
private:
|
||||
struct instance;
|
||||
|
||||
public:
|
||||
explicit opaque_pointer_converter(char const* name)
|
||||
{
|
||||
type_object.tp_name = const_cast<char *> (name);
|
||||
|
||||
lvalue_from_pytype<
|
||||
opaque_pointer_converter<ptr_type>,
|
||||
&opaque_pointer_converter<ptr_type>::type_object
|
||||
>();
|
||||
}
|
||||
|
||||
static PyObject* convert(ptr_type x)
|
||||
{
|
||||
PyObject *result = 0;
|
||||
|
||||
if (x != 0) {
|
||||
instance *o = PyObject_New (instance, &type_object);
|
||||
|
||||
if (o != 0) {
|
||||
o->x = x;
|
||||
result = &o->base_;
|
||||
}
|
||||
} else {
|
||||
result = detail::none();
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static typename ::boost::remove_pointer<ptr_type>::type&
|
||||
execute(instance &p_)
|
||||
{
|
||||
return *p_.x;
|
||||
}
|
||||
|
||||
private:
|
||||
static PyTypeObject type_object;
|
||||
|
||||
// This is a POD so we can use PyObject_Del on it, for example.
|
||||
struct instance
|
||||
{
|
||||
PyObject base_;
|
||||
ptr_type x;
|
||||
};
|
||||
};
|
||||
|
||||
template <class Pointer>
|
||||
PyTypeObject opaque_pointer_converter<Pointer>::type_object =
|
||||
{
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0,
|
||||
0,
|
||||
sizeof(typename opaque_pointer_converter<Pointer>::instance),
|
||||
0,
|
||||
::boost::python::detail::dealloc
|
||||
};
|
||||
}} // namespace boost::python
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
// MSC works without this workaround, but needs another one ...
|
||||
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
|
||||
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee)
|
||||
# elif BOOST_WORKAROUND(__GNUC__, < 3)
|
||||
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
|
||||
namespace boost { namespace python { \
|
||||
template<> \
|
||||
inline type_info type_id<Pointee>() { \
|
||||
return type_info (typeid (Pointee *)); \
|
||||
} \
|
||||
template<> \
|
||||
inline type_info type_id<const volatile Pointee &>() { \
|
||||
return type_info (typeid (Pointee *)); \
|
||||
} \
|
||||
}}
|
||||
# else
|
||||
# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
|
||||
namespace boost { namespace python { \
|
||||
template<> \
|
||||
inline type_info type_id(boost::type<Pointee>*) { \
|
||||
return type_info (typeid (Pointee *)); \
|
||||
} \
|
||||
template<> \
|
||||
inline type_info type_id( \
|
||||
boost::type<const volatile Pointee &>*) { \
|
||||
return type_info (typeid (Pointee *)); \
|
||||
} \
|
||||
}}
|
||||
# endif
|
||||
# endif // OPAQUE_POINTER_CONVERTER_HPP_
|
||||
@@ -14,6 +14,9 @@
|
||||
# pragma once
|
||||
# endif
|
||||
|
||||
#if defined(__ALPHA) && defined(__osf__) && defined(__DECCXX_VER)
|
||||
# include <pyconfig.h>
|
||||
#endif
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
|
||||
51
include/boost/python/return_opaque_pointer.hpp
Normal file
51
include/boost/python/return_opaque_pointer.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright Gottfried Ganßauge 2003. 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.
|
||||
/*
|
||||
* Generic Return value converter generator for opaque C++-pointers
|
||||
*/
|
||||
# ifndef RETURN_OPAQUE_POINTER_HPP_
|
||||
# define RETURN_OPAQUE_POINTER_HPP_
|
||||
# include <boost/python/opaque_pointer_converter.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
namespace detail {
|
||||
template <class Pointer>
|
||||
struct opaque_conversion_holder {
|
||||
inline PyObject *operator () (Pointer p) {
|
||||
static opaque_pointer_converter<Pointer> converter (
|
||||
typeid (Pointer).name());
|
||||
|
||||
return converter.convert(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
struct return_opaque_pointer_requires_a_pointer_type
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
|
||||
{}
|
||||
# endif
|
||||
;
|
||||
}
|
||||
|
||||
struct return_opaque_pointer
|
||||
{
|
||||
template <class R>
|
||||
struct apply
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ok = is_pointer<R>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
ok
|
||||
, detail::opaque_conversion_holder<R>
|
||||
, detail::return_opaque_pointer_requires_a_pointer_type<R>
|
||||
>::type type;
|
||||
};
|
||||
};
|
||||
}} // namespace boost::python
|
||||
# endif // RETURN_OPAQUE_POINTER_HPP_
|
||||
@@ -1,4 +1,4 @@
|
||||
To use this examples, just execute in the command-line:
|
||||
To use this examples, just execute the command-line:
|
||||
|
||||
pyste --module=<example> <example>.pyste
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
namespace basic {
|
||||
|
||||
struct C
|
||||
{
|
||||
virtual int f(int x = 10)
|
||||
@@ -19,3 +21,5 @@ int call_f(C& c, int x)
|
||||
{
|
||||
return c.f(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Class('C', 'basic.h')
|
||||
Function('call_f', 'basic.h')
|
||||
Class('basic::C', 'basic.h')
|
||||
Function('basic::call_f', 'basic.h')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
namespace test {
|
||||
namespace enums {
|
||||
|
||||
enum color { red, blue };
|
||||
|
||||
struct X
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
color = Enum('test::color', 'enums.h')
|
||||
color = Enum('enums::color', 'enums.h')
|
||||
rename(color.red, 'Red')
|
||||
rename(color.blue, 'Blue')
|
||||
X = Class('test::X', 'enums.h')
|
||||
X = Class('enums::X', 'enums.h')
|
||||
rename(X.choices.bad, 'Bad')
|
||||
rename(X.choices.good, 'Good')
|
||||
rename(X.choices, 'Choices')
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace header_test {
|
||||
|
||||
enum choice { red, blue };
|
||||
|
||||
void print_choice(choice c)
|
||||
std::string choice_str(choice c)
|
||||
{
|
||||
std::map<choice, std::string> choice_map;
|
||||
choice_map[red] = "red";
|
||||
choice_map[blue] = "blue";
|
||||
std::cout << "You chose: " << choice_map[c] << std::endl;
|
||||
return choice_map[c];
|
||||
}
|
||||
|
||||
struct C
|
||||
{
|
||||
choice c;
|
||||
|
||||
void print_()
|
||||
std::string get()
|
||||
{
|
||||
print_choice(c);
|
||||
return choice_str(c);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
namespace nested {
|
||||
|
||||
struct X
|
||||
{
|
||||
struct Y
|
||||
@@ -19,3 +20,5 @@ int X::staticXValue = 10;
|
||||
int X::Y::staticYValue = 20;
|
||||
|
||||
typedef X Root;
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Class('Root', 'nested.h')
|
||||
Class('nested::Root', 'nested.h')
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
Include('iostream')
|
||||
test = Wrapper('sum',
|
||||
'''
|
||||
const C sum(const C&, const C&)
|
||||
{
|
||||
std::cout << "sum!" << std::endl;
|
||||
return C();
|
||||
}
|
||||
'''
|
||||
)
|
||||
C = Class('C', 'operator.h')
|
||||
set_wrapper(C.operator['+'], test)
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <iostream>
|
||||
|
||||
namespace operators {
|
||||
|
||||
struct C
|
||||
{
|
||||
@@ -16,14 +17,15 @@ struct C
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
double operator()()
|
||||
{
|
||||
return x;
|
||||
return C::x;
|
||||
}
|
||||
|
||||
double operator()(double other)
|
||||
{
|
||||
return x + other;
|
||||
return C::x + other;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +40,4 @@ const C operator*(const C& lhs, const C& rhs)
|
||||
return c;
|
||||
}
|
||||
|
||||
std::ostream& operator <<( std::ostream& s, const C& c)
|
||||
{
|
||||
std::cout << "here";
|
||||
s << "C instance: ";
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
1
pyste/example/operators.pyste
Normal file
1
pyste/example/operators.pyste
Normal file
@@ -0,0 +1 @@
|
||||
Class('operators::C', 'operators.h')
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
namespace templates {
|
||||
|
||||
template <class X, class Y>
|
||||
struct Point
|
||||
{
|
||||
@@ -6,3 +7,4 @@ struct Point
|
||||
Y y;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
Point = Template('Point', 'templates.h')
|
||||
Point = Template('templates::Point', 'templates.h')
|
||||
rename(Point.x, 'i')
|
||||
rename(Point.y, 'j')
|
||||
IPoint = Point('int double')
|
||||
FPoint = Point('double int')
|
||||
FPoint = Point('double int', 'FPoint')
|
||||
rename(IPoint, 'IPoint')
|
||||
rename(IPoint.x, '_x_')
|
||||
rename(IPoint.x, 'x')
|
||||
rename(IPoint.y, 'y')
|
||||
|
||||
|
||||
16
pyste/example/unions.h
Normal file
16
pyste/example/unions.h
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace unions {
|
||||
|
||||
class UnionTest
|
||||
{
|
||||
public:
|
||||
union // unions are not supported for now
|
||||
{
|
||||
int i;
|
||||
short s1;
|
||||
short s2;
|
||||
} mBad;
|
||||
|
||||
int mGood;
|
||||
};
|
||||
|
||||
}
|
||||
2
pyste/example/unions.pyste
Normal file
2
pyste/example/unions.pyste
Normal file
@@ -0,0 +1,2 @@
|
||||
UnionTest = Class('unions::UnionTest', 'unions.h')
|
||||
exclude(UnionTest.mBad)
|
||||
23
pyste/example/virtual.h
Normal file
23
pyste/example/virtual.h
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
struct C
|
||||
{
|
||||
public:
|
||||
virtual int f()
|
||||
{
|
||||
return f_abs();
|
||||
}
|
||||
|
||||
const char* get_name()
|
||||
{
|
||||
return name();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int f_abs() = 0;
|
||||
|
||||
private:
|
||||
virtual const char* name() { return "C"; }
|
||||
};
|
||||
|
||||
int call_f(C& c) { return c.f(); }
|
||||
|
||||
1
pyste/example/virtual.pyste
Normal file
1
pyste/example/virtual.pyste
Normal file
@@ -0,0 +1 @@
|
||||
Class('C', 'virtual.h')
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace wrappertest {
|
||||
|
||||
std::vector<int> Range(int count)
|
||||
{
|
||||
std::vector<int> v;
|
||||
@@ -32,4 +34,6 @@ struct C
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Include('wrappertest_wrappers.h')
|
||||
|
||||
f = Function('Range', 'wrappertest.h')
|
||||
f = Function('wrappertest::Range', 'wrappertest.h')
|
||||
set_wrapper(f, 'RangeWrapper')
|
||||
|
||||
mul = Wrapper('MulWrapper',
|
||||
'''
|
||||
list MulWrapper(C& c, int value){
|
||||
list MulWrapper(wrappertest::C& c, int value){
|
||||
return VectorToList(c.Mul(value));
|
||||
}
|
||||
'''
|
||||
)
|
||||
|
||||
C = Class('C', 'wrappertest.h')
|
||||
C = Class('wrappertest::C', 'wrappertest.h')
|
||||
set_wrapper(C.Mul, mul)
|
||||
|
||||
@@ -20,7 +20,7 @@ list VectorToList(const std::vector<T> & v)
|
||||
}
|
||||
|
||||
list RangeWrapper(int count){
|
||||
return VectorToList(Range(count));
|
||||
return VectorToList(wrappertest::Range(count));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -53,7 +53,7 @@ class ClassExporter(Exporter):
|
||||
Exporter.SetDeclarations(self, declarations)
|
||||
decl = self.GetDeclaration(self.info.name)
|
||||
if isinstance(decl, Typedef):
|
||||
self.class_ = decl.type
|
||||
self.class_ = self.GetDeclaration(decl.type.name)
|
||||
if not self.info.rename:
|
||||
self.info.rename = decl.name
|
||||
else:
|
||||
@@ -195,6 +195,12 @@ class ClassExporter(Exporter):
|
||||
|
||||
constructors = [x for x in self.public_members if isinstance(x, Constructor)]
|
||||
self.constructors = constructors[:]
|
||||
# don't export the copy constructor if the class is abstract
|
||||
if self.class_.abstract:
|
||||
for cons in constructors:
|
||||
if cons.IsCopy():
|
||||
constructors.remove(cons)
|
||||
break
|
||||
if not constructors:
|
||||
# declare no_init
|
||||
self.Add('constructor', py_ns + 'no_init')
|
||||
@@ -360,10 +366,11 @@ class ClassExporter(Exporter):
|
||||
}
|
||||
|
||||
# converters which has a special name in python
|
||||
SPECIAL_CONVETERS = {
|
||||
SPECIAL_CONVERTERS = {
|
||||
'double' : '__float__',
|
||||
'float' : '__float__',
|
||||
'int' : '__int__',
|
||||
'long' : '__long__',
|
||||
}
|
||||
|
||||
|
||||
@@ -474,12 +481,15 @@ class ClassExporter(Exporter):
|
||||
# export them as simple functions with a pre-determined name
|
||||
|
||||
converters = [x for x in self.public_members if type(x) == ConverterOperator]
|
||||
|
||||
|
||||
def ConverterMethodName(converter):
|
||||
result_fullname = converter.result.name
|
||||
# extract the last name from the full name
|
||||
result_name = _ID(result_fullname.split('::')[-1])
|
||||
return 'to_' + result_name
|
||||
if result_fullname in self.SPECIAL_CONVERTERS:
|
||||
return self.SPECIAL_CONVERTERS[result_fullname]
|
||||
else:
|
||||
# extract the last name from the full name
|
||||
result_name = _ID(result_fullname.split('::')[-1])
|
||||
return 'to_' + result_name
|
||||
|
||||
for converter in converters:
|
||||
info = self.info['operator'][converter.result.name]
|
||||
@@ -605,12 +615,13 @@ class _VirtualWrapperGenerator(object):
|
||||
param_names_str = ', '.join(param_names)
|
||||
if param_names_str:
|
||||
param_names_str = ', ' + param_names_str
|
||||
decl += indent*2 + '%s%scall_method<%s>(self, "%s"%s);\n' %\
|
||||
decl += indent*2 + '%s%scall_method< %s >(self, "%s"%s);\n' %\
|
||||
(return_str, python, result, rename, param_names_str)
|
||||
decl += indent + '}\n'
|
||||
|
||||
# default implementations (with overloading)
|
||||
if not method.abstract:
|
||||
# only for classes that are not abstract, and public methods
|
||||
if not method.abstract and method.visibility == Scope.public:
|
||||
minArgs = method.minArgs
|
||||
maxArgs = method.maxArgs
|
||||
impl_names = self.DefaultImplementationNames(method)
|
||||
@@ -628,8 +639,6 @@ class _VirtualWrapperGenerator(object):
|
||||
'''Returns a list of lines, which should be put inside the class_
|
||||
statement to export this method.'''
|
||||
# dont define abstract methods
|
||||
if method.abstract:
|
||||
return []
|
||||
pyste = namespaces.pyste
|
||||
rename = self.info[method.name].rename or method.name
|
||||
default_names = self.DefaultImplementationNames(method)
|
||||
@@ -675,18 +684,25 @@ class _VirtualWrapperGenerator(object):
|
||||
|
||||
|
||||
def VirtualMethods(self):
|
||||
return [m for m in self.class_.members if type(m) == Method and m.virtual]
|
||||
|
||||
def IsVirtual(m):
|
||||
return type(m) == Method and m.virtual
|
||||
return [m for m in self.class_.members if IsVirtual(m)]
|
||||
|
||||
|
||||
|
||||
def Constructors(self):
|
||||
return [m for m in self.class_.members if isinstance(m, Constructor)]
|
||||
def IsValid(m):
|
||||
return isinstance(m, Constructor) and m.visibility == Scope.public
|
||||
return [m for m in self.class_.members if IsValid(m)]
|
||||
|
||||
|
||||
def GenerateDefinitions(self):
|
||||
defs = []
|
||||
for method in self.VirtualMethods():
|
||||
if not self.info[method.name].exclude:
|
||||
defs.extend(self.MethodDefinition(method))
|
||||
exclude = self.info[method.name].exclude
|
||||
# generate definitions only for public methods and non-abstract methods
|
||||
if method.visibility == Scope.public and not method.abstract and not exclude:
|
||||
defs.extend(self.MethodDefinition(method))
|
||||
return defs
|
||||
|
||||
|
||||
@@ -698,7 +714,7 @@ class _VirtualWrapperGenerator(object):
|
||||
code = 'struct %s: %s\n' % (self.wrapper_name, class_name)
|
||||
code += '{\n'
|
||||
# generate constructors (with the overloads for each one)
|
||||
for cons in self.Constructors():
|
||||
for cons in self.Constructors(): # only public constructors
|
||||
minArgs = cons.minArgs
|
||||
maxArgs = cons.maxArgs
|
||||
# from the min number of arguments to the max number, generate
|
||||
|
||||
@@ -59,7 +59,7 @@ class CppParser:
|
||||
if tail:
|
||||
tempfilename = tempfile.mktemp('.h')
|
||||
infilename = tempfilename
|
||||
shutil.copy(filename, infilename)
|
||||
shutil.copyfile(filename, infilename)
|
||||
f = file(infilename, 'a')
|
||||
f.write('\n\n'+tail)
|
||||
f.close()
|
||||
|
||||
@@ -221,14 +221,14 @@ class GCCXMLParser(object):
|
||||
bases = self.GetBases(element.get('bases'))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
context = self.GetDecl(element.get('context'))
|
||||
if isinstance(context, Class): # a nested class
|
||||
if isinstance(context, str):
|
||||
class_ = Class(name, context, [], abstract, bases)
|
||||
self.AddDecl(class_)
|
||||
else:
|
||||
# a nested class
|
||||
visib = element.get('access', Scope.public)
|
||||
class_ = NestedClass(
|
||||
name, context.FullName(), visib, [], abstract, bases)
|
||||
else:
|
||||
assert isinstance(context, str)
|
||||
class_ = Class(name, context, [], abstract, bases)
|
||||
self.AddDecl(class_)
|
||||
# we have to add the declaration of the class before trying
|
||||
# to parse its members, to avoid recursion.
|
||||
class_.location = location
|
||||
@@ -251,10 +251,6 @@ class GCCXMLParser(object):
|
||||
type_ = self.GetType(element.get('type'))
|
||||
min = element.get('min')
|
||||
max = element.get('max')
|
||||
if min:
|
||||
min = int(min)
|
||||
if max:
|
||||
max = int(max)
|
||||
array = ArrayType(type_.name, min, max, type_.const)
|
||||
self.Update(id, array)
|
||||
|
||||
@@ -349,7 +345,7 @@ class GCCXMLParser(object):
|
||||
|
||||
def ParseTypedef(self, id, element):
|
||||
name = element.get('name')
|
||||
type = self.GetDecl(element.get('type'))
|
||||
type = self.GetType(element.get('type'))
|
||||
context = self.GetDecl(element.get('context'))
|
||||
if isinstance(context, Class):
|
||||
context = context.FullName()
|
||||
@@ -362,12 +358,13 @@ class GCCXMLParser(object):
|
||||
name = element.get('name')
|
||||
location = self.GetLocation(element.get('location'))
|
||||
context = self.GetDecl(element.get('context'))
|
||||
if isinstance(context, Class):
|
||||
if isinstance(context, str):
|
||||
enum = Enumeration(name, context)
|
||||
self.AddDecl(enum) # in this case, is a top level decl
|
||||
else:
|
||||
visib = element.get('access', Scope.public)
|
||||
enum = ClassEnumeration(name, context.FullName(), visib)
|
||||
else:
|
||||
enum = Enumeration(name, context)
|
||||
self.AddDecl(enum) # in this case, is a top level decl
|
||||
|
||||
enum.location = location
|
||||
for child in element:
|
||||
if child.tag == 'EnumValue':
|
||||
@@ -383,7 +380,18 @@ class GCCXMLParser(object):
|
||||
|
||||
|
||||
def ParseUnion(self, id, element):
|
||||
self.Update(id, Declaration(element.get('name'), ''))
|
||||
name = element.get('name')
|
||||
context = self.GetDecl(element.get('context'))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
if isinstance(context, str):
|
||||
# a free union
|
||||
union = Union(name, context)
|
||||
self.AddDecl(union)
|
||||
else:
|
||||
visib = element.get('access', Scope.public)
|
||||
union = ClassUnion(name, context.FullName(), visib)
|
||||
union.location = location
|
||||
self.Update(id, union)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ class Function(Declaration):
|
||||
'returns a declaration of a pointer to this function'
|
||||
result = self.result.FullName()
|
||||
params = ', '.join([x.FullName() for x in self.parameters])
|
||||
return '(%s (*)(%s))%s' % (result, params, self.FullName())
|
||||
return '(%s (*)(%s))&%s' % (result, params, self.FullName())
|
||||
|
||||
|
||||
def _MinArgs(self):
|
||||
@@ -211,7 +211,7 @@ class Method(Function):
|
||||
const = ''
|
||||
if self.const:
|
||||
const = 'const'
|
||||
return '(%s (%s::*)(%s) %s)%s' %\
|
||||
return '(%s (%s::*)(%s) %s)&%s' %\
|
||||
(result, self.class_, params, const, self.FullName())
|
||||
|
||||
|
||||
@@ -445,8 +445,20 @@ class Typedef(Declaration):
|
||||
self.visibility = Scope.public
|
||||
|
||||
|
||||
class Union(Declaration):
|
||||
'Shallow declaration, because Unions are not supported yet'
|
||||
def __init__(self, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
|
||||
|
||||
|
||||
class ClassUnion(Union):
|
||||
|
||||
def __init__(self, name, class_, visib):
|
||||
Union.__init__(self, name, None)
|
||||
self.class_ = class_
|
||||
self.visibility = visib
|
||||
|
||||
def FullName(self):
|
||||
return '%s::%s' % (self.class_, self.name)
|
||||
|
||||
|
||||
|
||||
3
pyste/tests/.cvsignore
Normal file
3
pyste/tests/.cvsignore
Normal file
@@ -0,0 +1,3 @@
|
||||
*.pyc
|
||||
*.dll
|
||||
*.cpp
|
||||
@@ -72,7 +72,7 @@ class ClassBaseTest(Tester):
|
||||
self.TestType(param, FundamentalType, 'int', 'int', False)
|
||||
self.assertEqual(foo.namespace, None)
|
||||
self.assertEqual(
|
||||
foo.PointerDeclaration(), '(void (test::Base::*)(int) )test::Base::foo')
|
||||
foo.PointerDeclaration(), '(void (test::Base::*)(int) )&test::Base::foo')
|
||||
|
||||
def testX(self):
|
||||
'test the member x in class Base'
|
||||
@@ -109,7 +109,7 @@ class ClassBaseTest(Tester):
|
||||
self.TestType(simple.result, FundamentalType, 'bool', 'bool', False)
|
||||
self.assertEqual(
|
||||
simple.PointerDeclaration(),
|
||||
'(bool (test::Base::*)(const std::string &) )test::Base::simple')
|
||||
'(bool (test::Base::*)(const std::string &) )&test::Base::simple')
|
||||
|
||||
|
||||
def testZ(self):
|
||||
@@ -181,7 +181,7 @@ class FreeFuncTest(Tester):
|
||||
self.assertEqual(self.func.namespace, 'test')
|
||||
self.assertEqual(
|
||||
self.func.PointerDeclaration(),
|
||||
'(const test::Base & (*)(const std::string &, int))test::FreeFunc')
|
||||
'(const test::Base & (*)(const std::string &, int))&test::FreeFunc')
|
||||
|
||||
|
||||
def testResult(self):
|
||||
|
||||
19
pyste/tests/build_pyste_nt.bat
Normal file
19
pyste/tests/build_pyste_nt.bat
Normal file
@@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
setlocal
|
||||
set MODULE_NAME=%1
|
||||
set PYSTE_FILE=%2
|
||||
set BOOST_ROOT=d:/programming/libraries/boost-cvs
|
||||
set PYTHON_ROOT=c:/python
|
||||
set STLPORT_ROOT=d:/programming/libraries/stlport-4.5.3
|
||||
set PYSTE_FILE_DIR=%@PATH[%PYSTE_FILE]
|
||||
|
||||
python ../src/pyste.py -I%PYSTE_FILE_DIR --out=%MODULE_NAME.cpp --module=%MODULE_NAME %PYSTE_FILE
|
||||
|
||||
icl /nologo /LD /GR /GX -I%PYSTE_FILE_DIR -I%STLPORT_ROOT/stlport -I%BOOST_ROOT/boost -I%PYTHON_ROOT/include %MODULE_NAME.cpp /link /libpath:%PYTHON_ROOT/libs /libpath:%BOOST_ROOT/lib /libpath:%STLPORT_ROOT/lib boost_python.lib
|
||||
|
||||
rm %MODULE_NAME.cpp
|
||||
rm %MODULE_NAME.exp
|
||||
rm %MODULE_NAME.lib
|
||||
rm %MODULE_NAME.obj
|
||||
|
||||
endlocal
|
||||
27
pyste/tests/example_basicUT.py
Normal file
27
pyste/tests/example_basicUT.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import unittest
|
||||
import os
|
||||
|
||||
class BasicExampleTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
from basic import C, call_f
|
||||
|
||||
class D(C):
|
||||
def f(self, x=10):
|
||||
return x+1
|
||||
|
||||
d = D()
|
||||
c = C()
|
||||
|
||||
self.assertEqual(c.f(), 20)
|
||||
self.assertEqual(c.f(3), 6)
|
||||
self.assertEqual(d.f(), 11)
|
||||
self.assertEqual(d.f(3), 4)
|
||||
self.assertEqual(call_f(c), 20)
|
||||
self.assertEqual(call_f(c, 4), 8)
|
||||
self.assertEqual(call_f(d), 11)
|
||||
self.assertEqual(call_f(d, 3), 4)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
18
pyste/tests/example_enumsUT.py
Normal file
18
pyste/tests/example_enumsUT.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import unittest
|
||||
from enums import *
|
||||
|
||||
class EnumsTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
self.assertEqual(int(color.Red), 0)
|
||||
self.assertEqual(int(color.Blue), 1)
|
||||
|
||||
self.assertEqual(int(X.Choices.Good), 1)
|
||||
self.assertEqual(int(X.Choices.Bad), 2)
|
||||
x = X()
|
||||
self.assertEqual(x.set(x.Choices.Good), 1)
|
||||
self.assertEqual(x.set(x.Choices.Bad), 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
15
pyste/tests/example_header_testUT.py
Normal file
15
pyste/tests/example_header_testUT.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import unittest
|
||||
from header_test import *
|
||||
|
||||
class HeaderTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
self.assertEqual(choice.red, 0)
|
||||
self.assertEqual(choice.blue, 1)
|
||||
self.assertEqual(choice_str(choice.blue), 'blue')
|
||||
self.assertEqual(choice_str(choice.red), 'red')
|
||||
c = C()
|
||||
c.c = choice.blue
|
||||
self.assertEqual(c.get(), 'blue')
|
||||
c.c = choice.red
|
||||
self.assertEqual(c.get(), 'red')
|
||||
15
pyste/tests/example_nested.py
Normal file
15
pyste/tests/example_nested.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import unittest
|
||||
from nested import *
|
||||
|
||||
class NestedTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
self.assertEqual(Root.staticXValue, 10)
|
||||
self.assertEqual(Root.Y.staticYValue, 20)
|
||||
z = Root.Y.Z()
|
||||
z.valueZ = 3
|
||||
self.assertEqual(z.valueZ, 3)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
25
pyste/tests/example_operatorsUT.py
Normal file
25
pyste/tests/example_operatorsUT.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import unittest
|
||||
from operators import *
|
||||
|
||||
class OperatorTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
c = C()
|
||||
c.value = 3.0
|
||||
d = C()
|
||||
d.value = 2.0
|
||||
self.assertEqual(c.x, 10)
|
||||
self.assertEqual(C.x, 10)
|
||||
self.assertEqual(C.x, 10)
|
||||
self.assertEqual((c * d).value, 6.0)
|
||||
self.assertEqual((c + d).value, 5.0)
|
||||
self.assertEqual(int(c), 3)
|
||||
self.assertEqual(int(d), 2)
|
||||
self.assertEqual(c(), 10)
|
||||
self.assertEqual(d(), 10)
|
||||
self.assertEqual(c(3.0), 13.0)
|
||||
self.assertEqual(d(6.0), 16.0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
26
pyste/tests/example_templatesUT.py
Normal file
26
pyste/tests/example_templatesUT.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import unittest
|
||||
from templates import *
|
||||
|
||||
class TemplatesTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
fp = FPoint()
|
||||
fp.i = 3.0
|
||||
fp.j = 4
|
||||
ip = IPoint()
|
||||
ip.x = 10
|
||||
ip.y = 3.0
|
||||
|
||||
self.assertEqual(fp.i, 3.0)
|
||||
self.assertEqual(fp.j, 4)
|
||||
self.assertEqual(ip.x, 10)
|
||||
self.assertEqual(ip.y, 3.0)
|
||||
self.assertEqual(type(fp.i), float)
|
||||
self.assertEqual(type(fp.j), int)
|
||||
self.assertEqual(type(ip.x), int)
|
||||
self.assertEqual(type(ip.y), float)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
31
pyste/tests/example_virtual.py
Normal file
31
pyste/tests/example_virtual.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import unittest
|
||||
from virtual import *
|
||||
|
||||
class VirtualTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
|
||||
class D(C):
|
||||
def f_abs(self):
|
||||
return 3
|
||||
|
||||
class E(C):
|
||||
def f(self):
|
||||
return 10
|
||||
def name(self):
|
||||
return 'E'
|
||||
|
||||
d = D()
|
||||
e = E()
|
||||
|
||||
self.assertEqual(d.f(), 3)
|
||||
self.assertEqual(call_f(d), 3)
|
||||
self.assertEqual(e.f(), 10)
|
||||
self.assertEqual(call_f(e), 10)
|
||||
self.assertEqual(d.get_name(), 'C')
|
||||
self.assertEqual(e.get_name(), 'E')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
11
pyste/tests/example_wrappertestUT.py
Normal file
11
pyste/tests/example_wrappertestUT.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import unittest
|
||||
from wrappertest import *
|
||||
|
||||
class WrapperTest(unittest.TestCase):
|
||||
|
||||
def testIt(self):
|
||||
self.assertEqual(Range(10), range(10))
|
||||
self.assertEqual(C().Mul(10), [x*10 for x in range(10)])
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -11,4 +11,5 @@ if __name__ == '__main__':
|
||||
module = __import__(os.path.splitext(name)[0])
|
||||
tests.append(loader.loadTestsFromModule(module))
|
||||
runner = unittest.TextTestRunner()
|
||||
runner.run(unittest.TestSuite(tests))
|
||||
result = runner.run(unittest.TestSuite(tests))
|
||||
sys.exit(not result.wasSuccessful())
|
||||
|
||||
20
pyste/tests/test_all.bat
Normal file
20
pyste/tests/test_all.bat
Normal file
@@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
call build_pyste_nt basic ../example/basic.pyste
|
||||
call build_pyste_nt enums ../example/enums.pyste
|
||||
call build_pyste_nt header_test ../example/header_test.pyste
|
||||
call build_pyste_nt nested ../example/nested.pyste
|
||||
call build_pyste_nt operators ../example/operators.pyste
|
||||
call build_pyste_nt templates ../example/templates.pyste
|
||||
call build_pyste_nt virtual ../example/virtual.pyste
|
||||
call build_pyste_nt wrappertest ../example/wrappertest.pyste
|
||||
call build_pyste_nt unions ../example/unions.pyste
|
||||
|
||||
|
||||
runtests.py
|
||||
|
||||
if errorlevel != 0 goto end
|
||||
|
||||
rm *.dll
|
||||
rm *.pyc
|
||||
|
||||
:end
|
||||
@@ -124,6 +124,8 @@ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ;
|
||||
|
||||
bpl-test extract ;
|
||||
|
||||
bpl-test opaque ;
|
||||
|
||||
bpl-test pickle1 ;
|
||||
bpl-test pickle2 ;
|
||||
bpl-test pickle3 ;
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// 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 <string>
|
||||
#include <boost/python/operators.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/scope.hpp>
|
||||
#include <boost/python/manage_new_object.hpp>
|
||||
#include <string>
|
||||
#include "test_class.hpp"
|
||||
|
||||
// Just use math.h here; trying to use std::pow() causes too much
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
// embedded_hello -- A simple Boost.Python embedding example -- by
|
||||
// Dirk Gerrits
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <boost/python.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace python = boost::python;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include "test_class.hpp"
|
||||
#include <boost/python/extract.hpp>
|
||||
#include <boost/python/list.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
@@ -15,6 +14,7 @@
|
||||
#include <boost/python/implicit.hpp>
|
||||
#include <string>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "test_class.hpp"
|
||||
#include <cassert>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
@@ -20,18 +20,8 @@ int x_value(X const& x)
|
||||
|
||||
X make_x(int n) { return X(n); }
|
||||
|
||||
|
||||
// foo/bar -- a regression for a vc7 bug workaround
|
||||
struct bar {};
|
||||
struct foo
|
||||
{
|
||||
virtual void f() = 0;
|
||||
operator bar() const { return bar(); }
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(implicit_ext)
|
||||
{
|
||||
implicitly_convertible<foo,bar>();
|
||||
implicitly_convertible<int,X>();
|
||||
|
||||
def("x_value", x_value);
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
// to its suitability for any purpose.
|
||||
|
||||
|
||||
#include "simple_type.hpp"
|
||||
#include "complicated.hpp"
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
@@ -17,6 +15,8 @@
|
||||
#include <boost/python/errors.hpp>
|
||||
#include <boost/python/manage_new_object.hpp>
|
||||
#include <string.h>
|
||||
#include "simple_type.hpp"
|
||||
#include "complicated.hpp"
|
||||
|
||||
// Declare some straightforward extension types
|
||||
extern "C" void
|
||||
|
||||
75
test/opaque.cpp
Normal file
75
test/opaque.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright David Abrahams and Gottfried Ganssauge 2003. 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/return_opaque_pointer.hpp>
|
||||
# include <boost/python/def.hpp>
|
||||
# include <boost/python/module.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
|
||||
typedef struct opaque_ *opaque;
|
||||
typedef struct opaque2_ *opaque2;
|
||||
|
||||
opaque the_op = ((opaque) 0x47110815);
|
||||
opaque2 the_op2 = ((opaque2) 0x08154711);
|
||||
|
||||
opaque get() { return the_op; }
|
||||
|
||||
void use(opaque op)
|
||||
{
|
||||
if (op != the_op)
|
||||
throw std::runtime_error (std::string ("failed"));
|
||||
}
|
||||
|
||||
int useany(opaque op)
|
||||
{
|
||||
return op ? 1 : 0;
|
||||
}
|
||||
|
||||
opaque getnull()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void failuse (opaque op)
|
||||
{
|
||||
if (op == the_op)
|
||||
throw std::runtime_error (std::string ("success"));
|
||||
}
|
||||
|
||||
opaque2 get2 () { return the_op2; }
|
||||
|
||||
void use2 (opaque2 op)
|
||||
{
|
||||
if (op != the_op2)
|
||||
throw std::runtime_error (std::string ("failed"));
|
||||
}
|
||||
|
||||
void failuse2 (opaque2 op)
|
||||
{
|
||||
if (op == the_op2)
|
||||
throw std::runtime_error (std::string ("success"));
|
||||
}
|
||||
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque2_)
|
||||
|
||||
namespace bpl = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE(opaque_ext)
|
||||
{
|
||||
bpl::def (
|
||||
"get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
|
||||
bpl::def ("use", &::use);
|
||||
bpl::def ("useany", &::useany);
|
||||
bpl::def ("getnull", &::getnull, bpl::return_value_policy<bpl::return_opaque_pointer>());
|
||||
bpl::def ("failuse", &::failuse);
|
||||
|
||||
bpl::def (
|
||||
"get2",
|
||||
&::get2,
|
||||
bpl::return_value_policy<bpl::return_opaque_pointer>());
|
||||
bpl::def ("use2", &::use2);
|
||||
bpl::def ("failuse2", &::failuse2);
|
||||
}
|
||||
77
test/opaque.py
Normal file
77
test/opaque.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# Copyright Gottfried Ganßauge 2003. 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.
|
||||
"""
|
||||
>>> from opaque_ext import *
|
||||
>>> #
|
||||
>>> # Check for correct conversion
|
||||
>>> use(get())
|
||||
|
||||
# Check that None is converted to a NULL opaque pointer
|
||||
>>> useany(get())
|
||||
1
|
||||
>>> useany(None)
|
||||
0
|
||||
|
||||
# check that we don't lose type information by converting NULL opaque
|
||||
# pointers to None
|
||||
>>> assert getnull() is None
|
||||
>>> useany(getnull())
|
||||
0
|
||||
|
||||
>>> failuse(get())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
RuntimeError: success
|
||||
>>> #
|
||||
>>> # Check that there is no conversion from integers ...
|
||||
>>> use(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # ... and from strings to opaque objects
|
||||
>>> use("")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # Now check the same for another opaque pointer type
|
||||
>>> use2(get2())
|
||||
>>> failuse2(get2())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
RuntimeError: success
|
||||
>>> use2(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> use2("")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # Check that opaque types are distinct
|
||||
>>> use(get2())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> use2(get())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
"""
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
@@ -3,11 +3,11 @@
|
||||
// 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 <string>
|
||||
#include <boost/python/operators.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <string>
|
||||
#include "test_class.hpp"
|
||||
#if __GNUC__ != 2
|
||||
# include <ostream>
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
>>> (-y).value()
|
||||
39
|
||||
|
||||
>>> (x + y).value()
|
||||
3
|
||||
|
||||
>>> abs(y).value()
|
||||
39
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
For more information refer to boost/libs/python/doc/pickle.html.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
@@ -29,6 +27,8 @@
|
||||
#include <boost/python/extract.hpp>
|
||||
#include <boost/python/detail/api_placeholder.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A friendly class.
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
For more information refer to boost/libs/python/doc/pickle.html.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
@@ -26,6 +24,8 @@
|
||||
#include <boost/python/detail/api_placeholder.hpp>
|
||||
#include <boost/python/back_reference.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A friendly class.
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// 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/static_assert.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#include <boost/python/object/select_holder.hpp>
|
||||
#include <boost/python/has_back_reference.hpp>
|
||||
#include <boost/python/detail/not_specified.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#include <boost/function/function0.hpp>
|
||||
#include <memory>
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
// 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 <string>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <boost/python/handle.hpp>
|
||||
#include <boost/python/cast.hpp>
|
||||
|
||||
Reference in New Issue
Block a user