2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00

Compare commits

...

47 Commits

Author SHA1 Message Date
nobody
d7f4093bd1 This commit was manufactured by cvs2svn to create tag
'Version_1_30_1'.

[SVN r19444]
2003-08-04 17:55:29 +00:00
Dave Abrahams
ec0d1a6abc Updates for Boost 1.30.1
[SVN r19440]
2003-08-04 17:38:10 +00:00
Dave Abrahams
66f0c80336 Added Python 2.3 note.
[SVN r19438]
2003-08-04 17:01:29 +00:00
Dave Abrahams
9fa3d5c892 Backport bugfix from trunk
[SVN r19362]
2003-07-30 12:20:30 +00:00
nobody
97c0167660 This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r19146]
2003-07-16 10:53:07 +00:00
Dave Abrahams
f249fc9919 unused variable warning patch
[SVN r19130]
2003-07-15 19:35:14 +00:00
Dave Abrahams
8678283629 merged from trunk
[SVN r18264]
2003-04-16 14:32:58 +00:00
Dave Abrahams
88e7049a5b merged from trunk
[SVN r18054]
2003-03-22 17:29:34 +00:00
Dave Abrahams
955f716108 fix typo
[SVN r18025]
2003-03-20 02:53:47 +00:00
Ralf W. Grosse-Kunstleve
9178b9e6cc pyconfig.h included first only under Tru64/cxx
[SVN r18022]
2003-03-20 00:27:16 +00:00
Ralf W. Grosse-Kunstleve
6f0b083a51 restore Codewarrior builds
[SVN r17998]
2003-03-19 07:04:07 +00:00
Bruno da Silva de Oliveira
574e6b9e2c - Updated to reflect changes in declarations.py
[SVN r17997]
2003-03-19 05:55:28 +00:00
nobody
5bfc1e080d This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17996]
2003-03-19 05:54:27 +00:00
Bruno da Silva de Oliveira
d475fcaf7d - Fixed bug where the PointerDeclaration of functions and methods didn't have the & operator
[SVN r17994]
2003-03-19 05:03:49 +00:00
Bruno da Silva de Oliveira
85f324efb6 - Unit tests for the examples
[SVN r17992]
2003-03-19 03:08:53 +00:00
Bruno da Silva de Oliveira
08254b1fe7 - Fixed bug where an union that was a class member crashed pyste (unions are still not exported)
- Added support for int, double, float and long operators


[SVN r17991]
2003-03-19 02:57:31 +00:00
Bruno da Silva de Oliveira
d4b1b46e63 - Unit tests for the examples
[SVN r17990]
2003-03-19 02:55:30 +00:00
nobody
08f07b0cc6 This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17988]
2003-03-19 02:47:30 +00:00
Ralf W. Grosse-Kunstleve
2d0e0759c7 special code only for gcc <= 2.96
[SVN r17986]
2003-03-19 02:40:15 +00:00
Ralf W. Grosse-Kunstleve
130de54f23 fix for Visual C++ >= 7.1 as per David Abrahams
[SVN r17978]
2003-03-18 22:31:12 +00:00
Ralf W. Grosse-Kunstleve
3068b4ae13 gcc 2.96 compatibility
[SVN r17977]
2003-03-18 20:57:46 +00:00
Dave Abrahams
5867b87b60 Add funcptr FAQ
[SVN r17974]
2003-03-18 14:40:09 +00:00
Bruno da Silva de Oliveira
87953ae423 - Fixed bugs in Linux
[SVN r17969]
2003-03-18 05:16:01 +00:00
Bruno da Silva de Oliveira
eb252c0395 - Fixed bug where the permission bits were being copied to the tmp file
[SVN r17934]
2003-03-15 02:51:51 +00:00
nobody
2c0ec733ca This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17932]
2003-03-14 23:39:05 +00:00
Bruno da Silva de Oliveira
13df532aca - Fixed definition of private default implementations
[SVN r17930]
2003-03-14 23:36:44 +00:00
Bruno da Silva de Oliveira
c8747f6893 - Now generating wrappers for protected and private virtual methods
[SVN r17927]
2003-03-14 21:43:33 +00:00
nobody
69b9094dfc This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17902]
2003-03-14 02:49:25 +00:00
Bruno da Silva de Oliveira
5788cc83f3 no message
[SVN r17874]
2003-03-13 00:58:17 +00:00
Ralf W. Grosse-Kunstleve
0262c3bba9 adjustment for MIPSpro
[SVN r17864]
2003-03-12 22:59:46 +00:00
nobody
d6dd4e48e2 This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17843]
2003-03-12 13:51:19 +00:00
Dave Abrahams
b58503707f opaque pointer conversions from Gottfried.Ganssauge@haufe.de
Acknowledgements for all


[SVN r17839]
2003-03-12 13:38:18 +00:00
nobody
8c1a826ce8 This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17837]
2003-03-12 13:29:13 +00:00
Bruno da Silva de Oliveira
cc76f068ee - first RC version
[SVN r17827]
2003-03-12 03:40:44 +00:00
nobody
4efab432ab This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17826]
2003-03-12 01:39:29 +00:00
Ralf W. Grosse-Kunstleve
13b1f434ad pyconfig.h must be included before any system header (as per Python docs; essential for Python 2.3 under Tru64 Unix)
[SVN r17799]
2003-03-10 17:25:52 +00:00
Ralf W. Grosse-Kunstleve
c29241d859 non-template function make_function1 must be inline
[SVN r17791]
2003-03-09 17:26:06 +00:00
Dave Abrahams
fbe3d080e8 Fix for older EDGs
[SVN r17786]
2003-03-08 12:36:18 +00:00
Dave Abrahams
be96a3c4d6 Remove flotsam
[SVN r17783]
2003-03-08 08:53:19 +00:00
Dave Abrahams
70a967bac5 Remove flotsam
[SVN r17782]
2003-03-08 08:51:45 +00:00
Ralf W. Grosse-Kunstleve
a7ce37effa missing raw_function.hpp added; struct is_reference_to_class definition moved up
[SVN r17781]
2003-03-08 08:44:38 +00:00
Dave Abrahams
87c92775c9 Fix for Python 2.3 long->int conversion behavior change
[SVN r17779]
2003-03-08 05:28:54 +00:00
nobody
a15f7d5bf3 This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17778]
2003-03-08 03:53:20 +00:00
Dave Abrahams
a870ce20fc Added dangling_reference FAQ
Various idiomatic MPL cleanups in indirect_traits.hpp
raw_function support
Patches for CWPro7.2
Patches to pass tests under Python 2.3 with the new bool type.
Tests for member operators returning const objects
Fixes for testing Boost.Python under Cygwin


[SVN r17777]
2003-03-08 03:53:19 +00:00
Ralf W. Grosse-Kunstleve
e042228f45 MIPSpro compatibility
[SVN r17776]
2003-03-08 01:47:40 +00:00
Dave Abrahams
7c4cfe0589 Workaround for vc7 bug
[SVN r17709]
2003-03-03 17:24:07 +00:00
nobody
e24497a6cd This commit was manufactured by cvs2svn to create branch 'RC_1_30_0'.
[SVN r17693]
2003-03-01 19:43:06 +00:00
83 changed files with 2192 additions and 3037 deletions

1127
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

Binary file not shown.

View File

@@ -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 [#proto]_. The project also wanted to
test all of its C++ code using Python test scripts [#test]_. 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 [#feature]_, 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
=============
@@ -851,3 +924,24 @@ the ground up, we can approach design with new confidence and power.
.. [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
===========
Footnotes
===========
.. [#proto] 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++.
.. [#test] 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.
.. [#feature] These features were expressed very differently in v1 of
Boost.Python

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -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

View File

@@ -63,6 +63,23 @@
Initiative</a> at Lawrence Berkeley National Laboratories.
<hr>
<h2>Note for Python 2.3 users</h2>
This is a bugfix release only, and is <b>not</b> compatible with
Python 2.3. Boost 1.31.0, which will be compatible with Python
2.3, is due out shortly. In the meantime, if you need Python 2.3
compatibility, we suggest you get a CVS snapshot, either from the
<a href="../../../more/download.html#CVS">SourceForge anonymous
CVS</a> or from our mirror, updated nightly:
<pre>
cvs -d :pserver:anonymous@boost-consulting.com:/boost login
<i>no password; just hit return</i>
cvs -d :pserver:anonymous@boost-consulting.com:/boost co boost
</pre>
<hr>
<h2>Contents</h2>
<dl class="index">
@@ -97,7 +114,7 @@
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
17 November, 2002
4 August, 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>

View File

@@ -3,7 +3,7 @@
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
"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">
@@ -109,8 +109,8 @@
to Python.<br>
&nbsp;</dd>
<dt><b>HippoDraw</b> - <a href="http://www.slac.stanford.edu">Stanford
Linear Accelerator Center</a></dt>
<dt><b><a href=
"http://www.slac.stanford.edu/grp/ek/hippodraw/index.html">HippoDraw</a></b></dt>
<dd>
HippoDraw is a data analysis environment consisting of a canvas upon
@@ -120,8 +120,9 @@
so that all the manipulation can be done from either Python or the
GUI.
<p><a href="mailto:Paul_Kunz@SLAC.Stanford.EDU">Paul F. Kunz</a>
writes:</p>
<p>Before the web page came online, <a
href="mailto:Paul_Kunz@SLAC.Stanford.EDU">Paul F. Kunz</a>
wrote:</p>
<blockquote>
Don't have a web page for the project, but the organization's is <a
@@ -212,12 +213,12 @@
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
16 November, 2002
22 March, 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002. All Rights Reserved.</i></p>
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
</body>
</html>

View File

@@ -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> (&quot;Pie-Steh&quot;)
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

View File

@@ -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&lt;void (string s) &gt; funcptr;
void foo(funcptr fp)
{
fp(&quot;hello,world!&quot;);
}
BOOST_PYTHON_MODULE(test)
{
def(&quot;foo&quot;,foo) ;
}
</pre>
And then:
<pre>
&gt;&gt;&gt; def hello(s):
... print s
...
&gt;&gt;&gt; foo(hello)
hello, world!
</pre>
The short answer is: &quot;you can't&quot;. 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&amp; b, std::auto_ptr&lt;A&gt; 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>

View 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 - &lt;boost/python/opaque_pointer_converter.hpp&gt;</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
&lt;boost/python/opaque_pointer_converter.hpp&gt;</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&lt;P&gt;</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&lt;P&gt;</code></h3>
<p><code>opaque_pointer_converter&lt;&gt;</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&lt;class Pointer&gt;
struct opaque_pointer_converter
: to_python_converter&lt;
Pointer, opaque_pointer_converter&lt;Pointer&gt; &gt;
{
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>&copy; Copyright 2003 Haufe Mediengruppe. All Rights
Reserved.</i></p>
</body>
</html>

View File

@@ -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 - &lt;boost/python/raw_function.hpp&gt;</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 &lt;boost/python/raw_function.hpp&gt;</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 &lt;class F&gt;
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 &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/tuple.hpp&gt;
#include &lt;boost/python/dict.hpp&gt;
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/raw_function.hpp&gt;
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>
&gt;&gt;&gt; from raw_test import *
&gt;&gt;&gt; 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>&copy; Copyright <a href=
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
Reserved.</i></p>
</body>
</html>

View File

@@ -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>

View 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 - &lt;boost/python/return_opaque_pointer.hpp&gt;</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
&lt;boost/python/return_opaque_pointer.hpp&gt;</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 &lt;class R&gt; struct apply;
};
}}
</pre>
<h4><a name="return_opaque_pointer-spec-metafunctions"></a>Class
<code>return_opaque_pointer</code> metafunctions</h4>
<pre>
template &lt;class R&gt; struct apply
</pre>
<dl class="metafunction-semantics">
<dt><b>Returns:</b> <code>typedef
detail::opaque_conversion_holder&lt;R&gt;
type;</code></dt>
</dl>
<h2><a name="examples"></a>Example</h2>
<h3>C++ Module Definition</h3>
<pre>
# include &lt;boost/python/return_opaque_pointer.hpp&gt;
# include &lt;boost/python/def.hpp&gt;
# include &lt;boost/python/module.hpp&gt;
# include &lt;boost/python/return_value_policy.hpp&gt;
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&lt;bpl::return_opaque_pointer&gt;());
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>&copy; Copyright 2003 Haufe Mediengruppe. All Rights
Reserved.</i></p>
</body>
</html>

View File

@@ -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>

View File

@@ -84,7 +84,7 @@ namespace detail
// the type of holder that must be created. The 3rd argument is a
// reference to the Python type object to be created.
template <class T, class SelectHolder>
inline void register_class_to_python(mpl::true_ copyable, SelectHolder selector, T* = 0)
inline void register_class_to_python(mpl::true_, SelectHolder, T* = 0)
{
typedef typename SelectHolder::type holder;
force_instantiate(objects::class_cref_wrapper<T, objects::make_instance<T,holder> >());
@@ -92,7 +92,7 @@ namespace detail
}
template <class T, class SelectHolder>
inline void register_class_to_python(mpl::false_ copyable, SelectHolder selector, T* = 0)
inline void register_class_to_python(mpl::false_, SelectHolder, T* = 0)
{
SelectHolder::register_();
}

View File

@@ -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

View 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_

View File

@@ -47,7 +47,7 @@ template <>
struct value_destroyer<true,true>
{
template <class T>
static void execute(T const volatile* p)
static void execute(T const volatile*)
{
}
};
@@ -56,7 +56,7 @@ template <>
struct value_destroyer<false,true>
{
template <class T>
static void execute(T const volatile* p)
static void execute(T const volatile*)
{
}
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -6,9 +6,11 @@
#ifndef MAKE_INSTANCE_DWA200296_HPP
# define MAKE_INSTANCE_DWA200296_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/object/instance.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/detail/decref_guard.hpp>
# include <boost/python/detail/none.hpp>
namespace boost { namespace python { namespace objects {
@@ -24,6 +26,9 @@ struct make_instance_impl
PyTypeObject* type = Derived::get_class_object(x);
if (type == 0)
return python::detail::none();
PyObject* raw_result = type->tp_alloc(
type, objects::additional_instance_size<Holder>::value);

View File

@@ -34,6 +34,9 @@ struct make_ptr_instance
template <class U>
static inline PyTypeObject* get_class_object_impl(U const volatile* p)
{
if (p == 0)
return 0;
PyTypeObject* derived = get_derived_class_object(is_polymorphic<U>::type(), p);
if (derived)
return derived;

View File

@@ -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>

View 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_

View File

@@ -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>

View File

@@ -25,7 +25,10 @@ namespace detail
{
return incref(
object(
f(tuple(borrowed_reference(args)), dict(borrowed_reference(keywords)))
f(
tuple(borrowed_reference(args))
, keywords ? dict(borrowed_reference(keywords)) : dict()
)
).ptr()
);
}

View 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_

View File

@@ -1,76 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Exporting All Declarations from a Header</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="wrappers.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="theme/c%2B%2Bboost.gif">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Exporting All Declarations from a Header</b></font>
</td>
</tr>
</table>
<br>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="wrappers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<p>
Pyste also supports a mechanism to export all declarations found in a header
file. Suppose again our file, <tt>hello.h</tt>:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</span><span class=special>{
</span><span class=identifier>World</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>): </span><span class=identifier>msg</span><span class=special>(</span><span class=identifier>msg</span><span class=special>) {}
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
};
</span><span class=keyword>enum </span><span class=identifier>choice </span><span class=special>{ </span><span class=identifier>red</span><span class=special>, </span><span class=identifier>blue </span><span class=special>};
</span><span class=keyword>void </span><span class=identifier>show</span><span class=special>(</span><span class=identifier>choice </span><span class=identifier>c</span><span class=special>) { </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>&quot;value: &quot; </span><span class=special>&lt;&lt; (</span><span class=keyword>int</span><span class=special>)</span><span class=identifier>c </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>; }
</span></pre></code>
<p>
You can just use the <tt>AllFromHeader</tt> construct:</p>
<code><pre>
<span class=identifier>hello </span><span class=special>= </span><span class=identifier>AllFromHeader</span><span class=special>(</span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span></pre></code>
<p>
this will export all the declarations found in <tt>hello.h</tt>, which is equivalent
to write:</p>
<code><pre>
<span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>Enum</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;show&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span></pre></code>
<p>
Note that you can still use the functions <tt>rename</tt>, <tt>set_policy</tt>, <tt>exclude</tt>, etc. Just access
the members of the header object like this:</p>
<code><pre>
<span class=identifier>rename</span><span class=special>(</span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=string>&quot;Greet&quot;</span><span class=special>)
</span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>set</span><span class=special>, </span><span class=string>&quot;Set&quot;</span><span class=special>)
</span></pre></code>
<table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><a href="wrappers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
</tr>
</table>
<br>
<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
<font size="2">Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose. </font> </p>
</body>
</html>

View File

@@ -1,5 +0,0 @@
To use this examples, just execute in the command-line:
pyste --module=<example> <example>.pyste
For more information, please refer to the documentation.

View File

@@ -1,21 +0,0 @@
struct C
{
virtual int f(int x = 10)
{
return x*2;
}
int foo(int x=1){
return x+1;
}
};
int call_f(C& c)
{
return c.f();
}
int call_f(C& c, int x)
{
return c.f(x);
}

View File

@@ -1,2 +0,0 @@
Class('C', 'basic.h')
Function('call_f', 'basic.h')

View File

@@ -1,18 +0,0 @@
namespace test {
enum color { red, blue };
struct X
{
enum choices
{
good = 1,
bad = 2
};
int set(choices c)
{
return (int)c;
}
};
}

View File

@@ -1,8 +0,0 @@
color = Enum('test::color', 'enums.h')
rename(color.red, 'Red')
rename(color.blue, 'Blue')
X = Class('test::X', 'enums.h')
rename(X.choices.bad, 'Bad')
rename(X.choices.good, 'Good')
rename(X.choices, 'Choices')

View File

@@ -1,23 +0,0 @@
#include <iostream>
#include <map>
#include <string>
enum choice { red, blue };
void print_choice(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;
}
struct C
{
choice c;
void print_()
{
print_choice(c);
}
};

View File

@@ -1 +0,0 @@
AllFromHeader('header_test.h')

View File

@@ -1,21 +0,0 @@
struct X
{
struct Y
{
int valueY;
static int staticYValue;
struct Z
{
int valueZ;
};
};
static int staticXValue;
int valueX;
};
int X::staticXValue = 10;
int X::Y::staticYValue = 20;
typedef X Root;

View File

@@ -1 +0,0 @@
Class('Root', 'nested.h')

View File

@@ -1,47 +0,0 @@
#include <iostream>
struct C
{
static double x;
double value;
const C operator+(const C other) const
{
C c;
c.value = value + other.value;
return c;
}
operator int() const
{
return value;
}
double operator()()
{
return x;
}
double operator()(double other)
{
return x + other;
}
};
double C::x = 10;
const C operator*(const C& lhs, const C& rhs)
{
C c;
c.value = lhs.value * rhs.value;
return c;
}
std::ostream& operator <<( std::ostream& s, const C& c)
{
std::cout << "here";
s << "C instance: ";
return s;
}

View File

@@ -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)

View File

@@ -1,8 +0,0 @@
template <class X, class Y>
struct Point
{
X x;
Y y;
};

View File

@@ -1,8 +0,0 @@
Point = Template('Point', 'templates.h')
rename(Point.x, 'i')
rename(Point.y, 'j')
IPoint = Point('int double')
FPoint = Point('double int')
rename(IPoint, 'IPoint')
rename(IPoint.x, '_x_')

View File

@@ -1,35 +0,0 @@
#ifndef WRAPPER_TEST
#define WRAPPER_TEST
#include <vector>
std::vector<int> Range(int count)
{
std::vector<int> v;
v.reserve(count);
for (int i = 0; i < count; ++i){
v.push_back(i);
}
return v;
}
struct C
{
C() {}
std::vector<int> Mul(int value)
{
std::vector<int> res;
res.reserve(value);
std::vector<int>::const_iterator it;
std::vector<int> v(Range(value));
for (it = v.begin(); it != v.end(); ++it){
res.push_back(*it * value);
}
return res;
}
};
#endif

View File

@@ -1,15 +0,0 @@
Include('wrappertest_wrappers.h')
f = Function('Range', 'wrappertest.h')
set_wrapper(f, 'RangeWrapper')
mul = Wrapper('MulWrapper',
'''
list MulWrapper(C& c, int value){
return VectorToList(c.Mul(value));
}
'''
)
C = Class('C', 'wrappertest.h')
set_wrapper(C.Mul, mul)

View File

@@ -1,26 +0,0 @@
#ifndef WRAPPER_TEST_WRAPPERS
#define WRAPPER_TEST_WRAPPERS
#include <vector>
#include <boost/python.hpp>
#include "wrappertest.h"
using namespace boost::python;
template <class T>
list VectorToList(const std::vector<T> & v)
{
list res;
std::vector<T>::const_iterator it;
for(it = v.begin(); it != v.end(); ++it){
res.append(*it);
}
Py_XINCREF(res.ptr());
return res;
}
list RangeWrapper(int count){
return VectorToList(Range(count));
}
#endif

View File

@@ -1 +0,0 @@
*.pyc

View File

@@ -1,726 +0,0 @@
import exporters
from Exporter import Exporter
from declarations import *
from enumerate import enumerate
from settings import *
from CodeUnit import CodeUnit
from EnumExporter import EnumExporter
#==============================================================================
# ClassExporter
#==============================================================================
class ClassExporter(Exporter):
'Generates boost.python code to export a class declaration'
def __init__(self, info, parser_tail=None):
Exporter.__init__(self, info, parser_tail)
# sections of code
self.sections = {}
# template: each item in the list is an item into the class_<...>
# section.
self.sections['template'] = []
# constructor: each item in the list is a parameter to the class_
# constructor, like class_<C>(...)
self.sections['constructor'] = []
# inside: everything within the class_<> statement
self.sections['inside'] = []
# scope: items outside the class statement but within its scope.
# scope* s = new scope(class<>());
# ...
# delete s;
self.sections['scope'] = []
# declarations: outside the BOOST_PYTHON_MODULE macro
self.sections['declaration'] = []
self.sections['include'] = []
# a list of Constructor instances
self.constructors = []
self.wrapper_generator = None
# a list of code units, generated by nested declarations
self.nested_codeunits = []
def ScopeName(self):
return _ID(self.class_.FullName()) + '_scope'
def Name(self):
return self.class_.FullName()
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
decl = self.GetDeclaration(self.info.name)
if isinstance(decl, Typedef):
self.class_ = decl.type
if not self.info.rename:
self.info.rename = decl.name
else:
self.class_ = decl
self.public_members = \
[x for x in self.class_.members if x.visibility == Scope.public]
def Order(self):
'''Return the TOTAL number of bases that this class has, including the
bases' bases. Do this because base classes must be instantialized
before the derived classes in the module definition.
'''
def BasesCount(classname):
decl = self.GetDeclaration(classname)
bases = [x.name for x in decl.bases]
total = 0
for base in bases:
total += BasesCount(base)
return len(bases) + total
return BasesCount(self.class_.FullName())
def Export(self, codeunit, exported_names):
self.ExportBasics()
self.ExportBases(exported_names)
self.ExportConstructors()
self.ExportVariables()
self.ExportMethods()
self.ExportVirtualMethods()
self.ExportOperators()
self.ExportNestedClasses(exported_names)
self.ExportNestedEnums()
self.Write(codeunit)
def Write(self, codeunit):
indent = self.INDENT
boost_ns = namespaces.python
pyste_ns = namespaces.pyste
code = ''
# begin a scope for this class if needed
nested_codeunits = self.nested_codeunits
needs_scope = self.sections['scope'] or nested_codeunits
if needs_scope:
scope_name = self.ScopeName()
code += indent + boost_ns + 'scope* %s = new %sscope(\n' %\
(scope_name, boost_ns)
# export the template section
template_params = ', '.join(self.sections['template'])
code += indent + boost_ns + 'class_< %s >' % template_params
# export the constructor section
constructor_params = ', '.join(self.sections['constructor'])
code += '(%s)\n' % constructor_params
# export the inside section
in_indent = indent*2
for line in self.sections['inside']:
code += in_indent + line + '\n'
# write the scope section and end it
if not needs_scope:
code += indent + ';\n'
else:
code += indent + ');\n'
for line in self.sections['scope']:
code += indent + line + '\n'
# write the contents of the nested classes
for nested_unit in nested_codeunits:
code += '\n' + nested_unit.Section('module')
# close the scope
code += indent + 'delete %s;\n' % scope_name
# write the code to the module section in the codeunit
codeunit.Write('module', code + '\n')
# write the declarations to the codeunit
declarations = '\n'.join(self.sections['declaration'])
for nested_unit in nested_codeunits:
declarations += nested_unit.Section('declaration')
if declarations:
codeunit.Write('declaration', declarations + '\n')
# write the includes to the codeunit
includes = '\n'.join(self.sections['include'])
for nested_unit in nested_codeunits:
includes += nested_unit.Section('include')
if includes:
codeunit.Write('include', includes)
def Add(self, section, item):
'Add the item into the corresponding section'
self.sections[section].append(item)
def ExportBasics(self):
'Export the name of the class and its class_ statement'
self.Add('template', self.class_.FullName())
name = self.info.rename or self.class_.name
self.Add('constructor', '"%s"' % name)
def ExportBases(self, exported_names):
'Expose the bases of the class into the template section'
bases = self.class_.bases
bases_list = []
for base in bases:
if base.visibility == Scope.public and base.name in exported_names:
bases_list.append(base.name)
if bases_list:
code = namespaces.python + 'bases< %s > ' % \
(', '.join(bases_list))
self.Add('template', code)
def ExportConstructors(self):
'''Exports all the public contructors of the class, plus indicates if the
class is noncopyable.
'''
py_ns = namespaces.python
indent = self.INDENT
def init_code(cons):
'return the init<>() code for the given contructor'
param_list = [p.FullName() for p in cons.parameters]
min_params_list = param_list[:cons.minArgs]
max_params_list = param_list[cons.minArgs:]
min_params = ', '.join(min_params_list)
max_params = ', '.join(max_params_list)
init = py_ns + 'init< '
init += min_params
if max_params:
if min_params:
init += ', '
init += py_ns + ('optional< %s >' % max_params)
init += ' >()'
return init
constructors = [x for x in self.public_members if isinstance(x, Constructor)]
self.constructors = constructors[:]
if not constructors:
# declare no_init
self.Add('constructor', py_ns + 'no_init')
else:
# write the constructor with less parameters to the constructor section
smaller = None
for cons in constructors:
if smaller is None or len(cons.parameters) < len(smaller.parameters):
smaller = cons
assert smaller is not None
self.Add('constructor', init_code(smaller))
constructors.remove(smaller)
# write the rest to the inside section, using def()
for cons in constructors:
code = '.def(%s)' % init_code(cons)
self.Add('inside', code)
# check if the class is copyable
if not self.class_.HasCopyConstructor() or self.class_.abstract:
self.Add('template', namespaces.boost + 'noncopyable')
def ExportVariables(self):
'Export the variables of the class, both static and simple variables'
vars = [x for x in self.public_members if isinstance(x, Variable)]
for var in vars:
if self.info[var.name].exclude:
continue
name = self.info[var.name].rename or var.name
fullname = var.FullName()
if var.static:
code = '%s->attr("%s") = %s;' % (self.ScopeName(), name, fullname)
self.Add('scope', code)
else:
if var.type.const:
def_ = '.def_readonly'
else:
def_ = '.def_readwrite'
code = '%s("%s", &%s)' % (def_, name, fullname)
self.Add('inside', code)
printed_policy_warnings = {}
def CheckPolicy(self, m):
'Warns the user if this method needs a policy'
def IsString(type):
return type.const and type.name == 'char' and isinstance(type, PointerType)
needs_policy = isinstance(m.result, (ReferenceType, PointerType))
if IsString(m.result):
needs_policy = False
has_policy = self.info[m.name].policy is not None
if needs_policy and not has_policy:
warning = '---> Error: Method "%s" needs a policy.' % m.FullName()
if warning not in self.printed_policy_warnings:
print warning
print
self.printed_policy_warnings[warning] = 1
def ExportMethods(self):
'Export all the non-virtual methods of this class'
def OverloadName(m):
'Returns the name of the overloads struct for the given method'
return _ID(m.FullName()) + ('_overloads_%i_%i' % (m.minArgs, m.maxArgs))
declared = {}
def DeclareOverloads(m):
'Declares the macro for the generation of the overloads'
if not m.virtual:
func = m.name
code = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(%s, %s, %i, %i)\n'
code = code % (OverloadName(m), func, m.minArgs, m.maxArgs)
if code not in declared:
declared[code] = True
self.Add('declaration', code)
def Pointer(m):
'returns the correct pointer declaration for the method m'
# check if this method has a wrapper set for him
wrapper = self.info[method.name].wrapper
if wrapper:
return '&' + wrapper.FullName()
# return normal pointers to the methods of the class
is_unique = self.class_.IsUnique(m.name)
if is_unique:
return '&' + method.FullName()
else:
return method.PointerDeclaration()
def IsExportable(m):
'Returns true if the given method is exportable by this routine'
ignore = (Constructor, ClassOperator, Destructor)
return isinstance(m, Method) and not isinstance(m, ignore) and not m.virtual
methods = [x for x in self.public_members if IsExportable(x)]
for method in methods:
if self.info[method.name].exclude:
continue # skip this method
name = self.info[method.name].rename or method.name
# warn the user if this method needs a policy and doesn't have one
self.CheckPolicy(method)
# check for policies
policy = self.info[method.name].policy or ''
if policy:
policy = ', %s%s()' % (namespaces.python, policy.Code())
# check for overloads
overload = ''
if method.minArgs != method.maxArgs:
# add the overloads for this method
overload_name = OverloadName(method)
DeclareOverloads(method)
overload = ', %s%s()' % (namespaces.pyste, overload_name)
# build the .def string to export the method
pointer = Pointer(method)
code = '.def("%s", %s' % (name, pointer)
code += policy
code += overload
code += ')'
self.Add('inside', code)
# static method
if method.static:
code = '.staticmethod("%s")' % name
self.Add('inside', code)
# add wrapper code if this method has one
wrapper = self.info[method.name].wrapper
if wrapper and wrapper.code:
self.Add('declaration', wrapper.code)
def ExportVirtualMethods(self):
# check if this class has any virtual methods
has_virtual_methods = False
for member in self.class_.members:
if type(member) == Method and member.virtual:
has_virtual_methods = True
break
if has_virtual_methods:
generator = _VirtualWrapperGenerator(self.class_, self.info)
self.Add('template', generator.FullName())
for definition in generator.GenerateDefinitions():
self.Add('inside', definition)
self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT))
# operators natively supported by boost
BOOST_SUPPORTED_OPERATORS = '+ - * / % ^ & ! ~ | < > == != <= >= << >> && || += -='\
'*= /= %= ^= &= |= <<= >>='.split()
# create a map for faster lookup
BOOST_SUPPORTED_OPERATORS = dict(zip(BOOST_SUPPORTED_OPERATORS, range(len(BOOST_SUPPORTED_OPERATORS))))
# a dict of operators that are not directly supported by boost, but can be exposed
# simply as a function with a special signature
BOOST_RENAME_OPERATORS = {
'()' : '__call__',
}
# converters which has a special name in python
SPECIAL_CONVETERS = {
'double' : '__float__',
'float' : '__float__',
'int' : '__int__',
}
def ExportOperators(self):
'Export all member operators and free operators related to this class'
def GetFreeOperators():
'Get all the free (global) operators related to this class'
operators = []
for decl in self.declarations:
if isinstance(decl, Operator):
# check if one of the params is this class
for param in decl.parameters:
if param.name == self.class_.FullName():
operators.append(decl)
break
return operators
def GetOperand(param):
'Returns the operand of this parameter (either "self", or "other<type>")'
if param.name == self.class_.FullName():
return namespaces.python + 'self'
else:
return namespaces.python + ('other< %s >()' % param.name)
def HandleSpecialOperator(operator):
# gatter information about the operator and its parameters
result_name = operator.result.name
param1_name = ''
if operator.parameters:
param1_name = operator.parameters[0].name
# check for str
ostream = 'basic_ostream'
is_str = result_name.find(ostream) != -1 and param1_name.find(ostream) != -1
if is_str:
namespace = namespaces.python + 'self_ns::'
self_ = namespaces.python + 'self'
return '.def(%sstr(%s))' % (namespace, self_)
# is not a special operator
return None
frees = GetFreeOperators()
members = [x for x in self.public_members if type(x) == ClassOperator]
all_operators = frees + members
operators = [x for x in all_operators if not self.info['operator'][x.name].exclude]
for operator in operators:
# gatter information about the operator, for use later
wrapper = self.info['operator'][operator.name].wrapper
if wrapper:
pointer = '&' + wrapper.FullName()
if wrapper.code:
self.Add('declaration', wrapper.code)
elif isinstance(operator, ClassOperator) and self.class_.IsUnique(operator.name):
pointer = '&' + operator.FullName()
else:
pointer = operator.PointerDeclaration()
rename = self.info['operator'][operator.name].rename
# check if this operator will be exported as a method
export_as_method = wrapper or rename or operator.name in self.BOOST_RENAME_OPERATORS
# check if this operator has a special representation in boost
special_code = HandleSpecialOperator(operator)
has_special_representation = special_code is not None
if export_as_method:
# export this operator as a normal method, renaming or using the given wrapper
if not rename:
if wrapper:
rename = wrapper.name
else:
rename = self.BOOST_RENAME_OPERATORS[operator.name]
policy = ''
policy_obj = self.info['operator'][operator.name].policy
if policy_obj:
policy = ', %s()' % policy_obj.Code()
self.Add('inside', '.def("%s", %s%s)' % (rename, pointer, policy))
elif has_special_representation:
self.Add('inside', special_code)
elif operator.name in self.BOOST_SUPPORTED_OPERATORS:
# export this operator using boost's facilities
op = operator
is_unary = isinstance(op, Operator) and len(op.parameters) == 1 or\
isinstance(op, ClassOperator) and len(op.parameters) == 0
if is_unary:
self.Add('inside', '.def( %s%sself )' % \
(operator.name, namespaces.python))
else:
# binary operator
if len(operator.parameters) == 2:
left_operand = GetOperand(operator.parameters[0])
right_operand = GetOperand(operator.parameters[1])
else:
left_operand = namespaces.python + 'self'
right_operand = GetOperand(operator.parameters[0])
self.Add('inside', '.def( %s %s %s )' % \
(left_operand, operator.name, right_operand))
# export the converters.
# 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
for converter in converters:
info = self.info['operator'][converter.result.name]
# check if this operator should be excluded
if info.exclude:
continue
special_code = HandleSpecialOperator(converter)
if info.rename or not special_code:
# export as method
name = info.rename or ConverterMethodName(converter)
if self.class_.IsUnique(converter.name):
pointer = '&' + converter.FullName()
else:
pointer = converter.PointerDeclaration()
policy_code = ''
if info.policy:
policy_code = ', %s()' % info.policy.Code()
self.Add('inside', '.def("%s", %s%s)' % (name, pointer, policy_code))
elif special_code:
self.Add('inside', special_code)
def ExportNestedClasses(self, exported_names):
nested_classes = [x for x in self.public_members if isinstance(x, NestedClass)]
for nested_class in nested_classes:
nested_info = self.info[nested_class.name]
nested_info.include = self.info.include
nested_info.name = nested_class.FullName()
exporter = ClassExporter(nested_info)
exporter.SetDeclarations(self.declarations + [nested_class])
codeunit = CodeUnit(None)
exporter.Export(codeunit, exported_names)
self.nested_codeunits.append(codeunit)
def ExportNestedEnums(self):
nested_enums = [x for x in self.public_members if isinstance(x, ClassEnumeration)]
for enum in nested_enums:
enum_info = self.info[enum.name]
enum_info.include = self.info.include
enum_info.name = enum.FullName()
exporter = EnumExporter(enum_info)
exporter.SetDeclarations(self.declarations + [enum])
codeunit = CodeUnit(None)
exporter.Export(codeunit, None)
self.nested_codeunits.append(codeunit)
def _ID(name):
'Returns the name as a valid identifier'
for invalidchar in ('::', '<', '>', ' ', ','):
name = name.replace(invalidchar, '_')
# avoid duplications of '_' chars
names = [x for x in name.split('_') if x]
return '_'.join(names)
#==============================================================================
# Virtual Wrapper utils
#==============================================================================
def _ParamsInfo(m, count=None):
if count is None:
count = len(m.parameters)
param_names = ['p%i' % i for i in range(count)]
param_types = [x.FullName() for x in m.parameters[:count]]
params = ['%s %s' % (t, n) for t, n in zip(param_types, param_names)]
#for i, p in enumerate(m.parameters[:count]):
# if p.default is not None:
# #params[i] += '=%s' % p.default
# params[i] += '=%s' % (p.name + '()')
params = ', '.join(params)
return params, param_names, param_types
class _VirtualWrapperGenerator(object):
'Generates code to export the virtual methods of the given class'
def __init__(self, class_, info):
self.class_ = class_
self.info = info
self.wrapper_name = _ID(class_.FullName()) + '_Wrapper'
def DefaultImplementationNames(self, method):
'''Returns a list of default implementations for this method, one for each
number of default arguments. Always returns at least one name, and return from
the one with most arguments to the one with the least.
'''
base_name = 'default_' + method.name
minArgs = method.minArgs
maxArgs = method.maxArgs
if minArgs == maxArgs:
return [base_name]
else:
return [base_name + ('_%i' % i) for i in range(minArgs, maxArgs+1)]
def Declaration(self, method, indent):
'''Returns a string with the declarations of the virtual wrapper and
its default implementations. This string must be put inside the Wrapper
body.
'''
pyste = namespaces.pyste
python = namespaces.python
rename = self.info[method.name].rename or method.name
result = method.result.FullName()
return_str = 'return '
if result == 'void':
return_str = ''
params, param_names, param_types = _ParamsInfo(method)
constantness = ''
if method.const:
constantness = ' const'
# call_method callback
decl = indent + '%s %s(%s)%s {\n' % (result, method.name, params, constantness)
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' %\
(return_str, python, result, rename, param_names_str)
decl += indent + '}\n'
# default implementations (with overloading)
if not method.abstract:
minArgs = method.minArgs
maxArgs = method.maxArgs
impl_names = self.DefaultImplementationNames(method)
for impl_name, argNum in zip(impl_names, range(minArgs, maxArgs+1)):
params, param_names, param_types = _ParamsInfo(method, argNum)
decl += '\n'
decl += indent + '%s %s(%s)%s {\n' % (result, impl_name, params, constantness)
decl += indent*2 + '%s%s::%s(%s);\n' % \
(return_str, self.class_.FullName(), method.name, ', '.join(param_names))
decl += indent + '}\n'
return decl
def MethodDefinition(self, method):
'''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)
class_name = self.class_.FullName()
wrapper_name = pyste + self.wrapper_name
result = method.result.FullName()
is_method_unique = self.class_.IsUnique(method.name)
constantness = ''
if method.const:
constantness = ' const'
# create a list of default-impl pointers
minArgs = method.minArgs
maxArgs = method.maxArgs
if is_method_unique:
default_pointers = ['&%s::%s' % (wrapper_name, x) for x in default_names]
else:
default_pointers = []
for impl_name, argNum in zip(default_names, range(minArgs, maxArgs+1)):
param_list = [x.FullName() for x in method.parameters[:argNum]]
params = ', '.join(param_list)
signature = '%s (%s::*)(%s)%s' % (result, wrapper_name, params, constantness)
default_pointer = '(%s)%s::%s' % (signature, wrapper_name, impl_name)
default_pointers.append(default_pointer)
# get the pointer of the method
if is_method_unique:
pointer = '&' + method.FullName()
else:
pointer = method.PointerDeclaration()
# generate the defs
definitions = []
# basic def
definitions.append('.def("%s", %s, %s)' % (rename, pointer, default_pointers[-1]))
for default_pointer in default_pointers[:-1]:
definitions.append('.def("%s", %s)' % (rename, default_pointer))
return definitions
def FullName(self):
return namespaces.pyste + self.wrapper_name
def VirtualMethods(self):
return [m for m in self.class_.members if type(m) == Method and m.virtual]
def Constructors(self):
return [m for m in self.class_.members if isinstance(m, Constructor)]
def GenerateDefinitions(self):
defs = []
for method in self.VirtualMethods():
if not self.info[method.name].exclude:
defs.extend(self.MethodDefinition(method))
return defs
def GenerateVirtualWrapper(self, indent):
'Return the wrapper for this class'
# generate the class code
class_name = self.class_.FullName()
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():
minArgs = cons.minArgs
maxArgs = cons.maxArgs
# from the min number of arguments to the max number, generate
# all version of the given constructor
cons_code = ''
for argNum in range(minArgs, maxArgs+1):
params, param_names, param_types = _ParamsInfo(cons, argNum)
if params:
params = ', ' + params
cons_code += indent + '%s(PyObject* self_%s):\n' % \
(self.wrapper_name, params)
cons_code += indent*2 + '%s(%s), self(self_) {}\n\n' % \
(class_name, ', '.join(param_names))
code += cons_code
# generate the body
body = []
for method in self.VirtualMethods():
if not self.info[method.name].exclude:
body.append(self.Declaration(method, indent))
body = '\n'.join(body)
code += body + '\n'
# add the self member
code += indent + 'PyObject* self;\n'
code += '};\n'
return code

View File

@@ -1,78 +0,0 @@
from settings import *
#==============================================================================
# RemoveDuplicatedLines
#==============================================================================
def RemoveDuplicatedLines(text):
includes = text.splitlines()
d = dict([(include, 0) for include in includes])
return '\n'.join(d.keys())
#==============================================================================
# CodeUnit
#==============================================================================
class CodeUnit:
'''
Represents a cpp file, where other objects can write in one of the
predefined sections.
The avaiable sections are:
include - The include area of the cpp file
declaration - The part before the module definition
module - Inside the BOOST_PYTHON_MODULE macro
'''
USING_BOOST_NS = True
def __init__(self, modulename):
self.modulename = modulename
# define the avaiable sections
self.code = {}
self.code['include'] = ''
self.code['declaration'] = ''
self.code['module'] = ''
def Write(self, section, code):
'write the given code in the section of the code unit'
if section not in self.code:
raise RuntimeError, 'Invalid CodeUnit section: %s' % section
self.code[section] += code
def Section(self, section):
return self.code[section]
def Save(self, filename):
'Writes this code unit to the filename'
space = '\n\n'
fout = file(filename, 'w')
# includes
includes = RemoveDuplicatedLines(self.code['include'])
fout.write('\n' + self._leftEquals('Includes'))
fout.write('#include <boost/python.hpp>\n')
fout.write(includes)
fout.write(space)
# using
if self.USING_BOOST_NS:
fout.write(self._leftEquals('Using'))
fout.write('using namespace boost::python;\n\n')
# declarations
if self.code['declaration']:
pyste_namespace = namespaces.pyste[:-2]
fout.write(self._leftEquals('Declarations'))
fout.write('namespace %s {\n\n\n' % pyste_namespace)
fout.write(self.code['declaration'])
fout.write('\n\n}// namespace %s\n' % pyste_namespace)
fout.write(space)
# module
fout.write(self._leftEquals('Module'))
fout.write('BOOST_PYTHON_MODULE(%s)\n{\n' % self.modulename)
fout.write(self.code['module'])
fout.write('}\n')
def _leftEquals(self, s):
s = '// %s ' % s
return s + ('='*(80-len(s))) + '\n'

View File

@@ -1,94 +0,0 @@
from GCCXMLParser import ParseDeclarations
import tempfile
import shutil
import os
import os.path
import settings
class CppParserError(Exception): pass
class CppParser:
'Parses a header file and returns a list of declarations'
def __init__(self, includes=None, defines=None):
'includes and defines ar the directives given to gcc'
if includes is None:
includes = []
if defines is None:
defines = []
self.includes = includes
self.defines = defines
def _includeparams(self, filename):
includes = self.includes[:]
filedir = os.path.dirname(filename)
if not filedir:
filedir = '.'
includes.insert(0, filedir)
includes = ['-I "%s"' % x for x in includes]
return ' '.join(includes)
def _defineparams(self):
defines = ['-D "%s"' % x for x in self.defines]
return ' '.join(defines)
def FindFileName(self, include):
if os.path.isfile(include):
return include
for path in self.includes:
filename = os.path.join(path, include)
if os.path.isfile(filename):
return filename
name = os.path.basename(include)
raise RuntimeError, 'Header file "%s" not found!' % name
def parse(self, include, symbols=None, tail=None):
'''Parses the given filename, and returns (declaration, header). The
header returned is normally the same as the given to this method,
except if tail is not None: in this case, the header is copied to a temp
filename and the tail code is appended to it before being passed on to gcc.
This temp filename is then returned.
'''
filename = self.FindFileName(include)
# copy file to temp folder, if needed
if tail:
tempfilename = tempfile.mktemp('.h')
infilename = tempfilename
shutil.copy(filename, infilename)
f = file(infilename, 'a')
f.write('\n\n'+tail)
f.close()
else:
infilename = filename
xmlfile = tempfile.mktemp('.xml')
try:
# get the params
includes = self._includeparams(filename)
defines = self._defineparams()
# call gccxml
cmd = 'gccxml %s %s %s -fxml=%s' \
% (includes, defines, infilename, xmlfile)
if symbols:
cmd += ' -fxml-start=' + ','.join(symbols)
status = os.system(cmd)
if status != 0 or not os.path.isfile(xmlfile):
raise CppParserError, 'Error executing gccxml'
# parse the resulting xml
declarations = ParseDeclarations(xmlfile)
# return the declarations
return declarations, infilename
finally:
if settings.DEBUG and os.path.isfile(xmlfile):
filename = os.path.basename(include)
shutil.copy(xmlfile, os.path.splitext(filename)[0] + '.xml')
# delete the temporary files
try:
os.remove(xmlfile)
if tail:
os.remove(tempfilename)
except OSError: pass

View File

@@ -1,30 +0,0 @@
from Exporter import Exporter
from settings import *
#==============================================================================
# EnumExporter
#==============================================================================
class EnumExporter(Exporter):
'Exports enumerators'
def __init__(self, info):
Exporter.__init__(self, info)
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
self.enum = self.GetDeclaration(self.info.name)
def Export(self, codeunit, expoted_names):
indent = self.INDENT
in_indent = self.INDENT*2
rename = self.info.rename or self.enum.name
full_name = self.enum.FullName()
code = indent + namespaces.python + 'enum_< %s >("%s")\n' % (full_name, rename)
for name in self.enum.values:
rename = self.info[name].rename or name
value_fullname = self.enum.ValueFullName(name)
code += in_indent + '.value("%s", %s)\n' % (rename, value_fullname)
code += indent + ';\n\n'
codeunit.Write('module', code)

View File

@@ -1,69 +0,0 @@
import os.path
#==============================================================================
# Exporter
#==============================================================================
class Exporter:
'Base class for objects capable to generate boost.python code.'
INDENT = ' ' * 4
def __init__(self, info, parser_tail=None):
self.info = info
self.parser_tail = parser_tail
def Parse(self, parser):
self.parser = parser
header = self.info.include
tail = self.parser_tail
declarations, parser_header = parser.parse(header, tail=tail)
self.parser_header = parser_header
self.SetDeclarations(declarations)
def SetDeclarations(self, declarations):
self.declarations = declarations
def GenerateCode(self, codeunit, exported_names):
self.WriteInclude(codeunit)
self.Export(codeunit, exported_names)
def WriteInclude(self, codeunit):
codeunit.Write('include', '#include <%s>\n' % self.info.include)
def Export(self, codeunit, exported_names):
'subclasses must override this to do the real work'
pass
def Name(self):
'''Returns the name of this Exporter. The name will be added to the
list of names exported, which may have a use for other exporters.
'''
return None
def GetDeclarations(self, fullname):
decls = [x for x in self.declarations if x.FullName() == fullname]
if not decls:
raise RuntimeError, 'no %s declaration found!' % fullname
return decls
def GetDeclaration(self, fullname):
decls = self.GetDeclarations(fullname)
assert len(decls) == 1
return decls[0]
def Order(self):
'''Returns a number that indicates to which order this exporter
belongs. The exporters will be called from the lowest order to the
highest order.
This function will only be called after Parse has been called.
'''
return None # don't care

View File

@@ -1,85 +0,0 @@
from Exporter import Exporter
from policies import *
from declarations import *
from settings import *
class FunctionExporter(Exporter):
'Generates boost.python code to export the given function.'
def __init__(self, info, tail=None):
Exporter.__init__(self, info, tail)
def Export(self, codeunit, exported_names):
decls = self.GetDeclarations(self.info.name)
for decl in decls:
self.CheckPolicy(decl)
self.ExportDeclaration(decl, len(decls) == 1, codeunit)
self.GenerateOverloads(decls, codeunit)
def Name(self):
return self.info.name
def CheckPolicy(self, func):
'Warns the user if this function needs a policy'
def IsString(type):
return type.const and type.name == 'char' and isinstance(type, PointerType)
needs_policy = isinstance(func.result, (ReferenceType, PointerType))
if IsString(func.result):
needs_policy = False
if needs_policy and self.info.policy is None:
print '---> Error: Function "%s" needs a policy.' % func.FullName()
print
def ExportDeclaration(self, decl, unique, codeunit):
name = self.info.rename or decl.name
defs = namespaces.python + 'def("%s", ' % name
wrapper = self.info.wrapper
if wrapper:
pointer = '&' + wrapper.FullName()
elif not unique:
pointer = decl.PointerDeclaration()
else:
pointer = '&' + decl.FullName()
defs += pointer
defs += self.PolicyCode()
overload = self.OverloadName(decl)
if overload:
defs += ', %s()' % (namespaces.pyste + overload)
defs += ');'
codeunit.Write('module', self.INDENT + defs + '\n')
# add the code of the wrapper
if wrapper and wrapper.code:
codeunit.Write('declaration', code + '\n')
def OverloadName(self, decl):
if decl.minArgs != decl.maxArgs:
return '%s_overloads_%i_%i' % \
(decl.name, decl.minArgs, decl.maxArgs)
else:
return ''
def GenerateOverloads(self, declarations, codeunit):
codes = {}
for decl in declarations:
overload = self.OverloadName(decl)
if overload and overload not in codes:
code = 'BOOST_PYTHON_FUNCTION_OVERLOADS(%s, %s, %i, %i)' %\
(overload, decl.FullName(), decl.minArgs, decl.maxArgs)
codeunit.Write('declaration', code + '\n')
codes[overload] = None
def PolicyCode(self):
policy = self.info.policy
if policy is not None:
assert isinstance(policy, Policy)
return ', %s()' % policy.Code()
else:
return ''

View File

@@ -1,395 +0,0 @@
from declarations import *
from elementtree.ElementTree import ElementTree
from xml.parsers.expat import ExpatError
from copy import deepcopy
class InvalidXMLError(Exception): pass
class ParserError(Exception): pass
class InvalidContextError(ParserError): pass
class GCCXMLParser(object):
'Parse a GCC_XML file and extract the top-level declarations.'
interested_tags = {'Class':0, 'Function':0, 'Variable':0, 'Enumeration':0}
def Parse(self, filename):
self.elements = self.GetElementsFromXML(filename)
# high level declarations
self.declarations = []
# parse the elements
for id in self.elements:
element, decl = self.elements[id]
if decl is None:
try:
self.ParseElement(id, element)
except InvalidContextError:
pass # ignore those nodes with invalid context
# (workaround gccxml bug)
def Declarations(self):
return self.declarations
def AddDecl(self, decl):
self.declarations.append(decl)
def ParseElement(self, id, element):
method = 'Parse' + element.tag
if hasattr(self, method):
func = getattr(self, method)
func(id, element)
def GetElementsFromXML(self,filename):
'Extracts a dictionary of elements from the gcc_xml file.'
tree = ElementTree()
try:
tree.parse(filename)
except ExpatError:
raise InvalidXMLError, 'Not a XML file: %s' % filename
root = tree.getroot()
if root.tag != 'GCC_XML':
raise InvalidXMLError, 'Not a valid GCC_XML file'
# build a dictionary of id -> element, None
elementlist = root.getchildren()
elements = {}
for element in elementlist:
id = element.get('id')
if id:
elements[id] = element, None
return elements
def GetDecl(self, id):
if id not in self.elements:
if id == '_0':
raise InvalidContextError, 'Invalid context found in the xml file.'
else:
msg = 'ID not found in elements: %s' % id
raise ParserError, msg
elem, decl = self.elements[id]
if decl is None:
self.ParseElement(id, elem)
elem, decl = self.elements[id]
if decl is None:
raise ParserError, 'Could not parse element: %s' % elem.tag
return decl
def GetType(self, id):
const = False
volatile = False
if id[-1] == 'v':
volatile = True
id = id[:-1]
if id[-1] == 'c':
const = True
id = id[:-1]
decl = self.GetDecl(id)
if isinstance(decl, Type):
res = deepcopy(decl)
if const:
res.const = const
if volatile:
res.volatile = volatile
else:
res = Type(decl.FullName(), const)
res.volatile = volatile
return res
def GetLocation(self, location):
file, line = location.split(':')
file = self.GetDecl(file)
return file, int(line)
def Update(self, id, decl):
element, _ = self.elements[id]
self.elements[id] = element, decl
def ParseNamespace(self, id, element):
namespace = element.get('name')
context = element.get('context')
if context:
outerns = self.GetDecl(context)
if not outerns.endswith('::'):
outerns += '::'
namespace = outerns + namespace
if namespace.startswith('::'):
namespace = namespace[2:]
self.Update(id, namespace)
def ParseFile(self, id, element):
filename = element.get('name')
self.Update(id, filename)
def ParseVariable(self, id, element):
# in gcc_xml, a static Field is declared as a Variable, so we check
# this and call the Field parser if apply.
context = self.GetDecl(element.get('context'))
if isinstance(context, Class):
self.ParseField(id, element)
elem, decl = self.elements[id]
decl.static = True
else:
namespace = context
name = element.get('name')
type_ = self.GetType(element.get('type'))
location = self.GetLocation(element.get('location'))
variable = Variable(type_, name, namespace)
variable.location = location
self.AddDecl(variable)
self.Update(id, variable)
def GetArguments(self, element):
args = []
for child in element:
if child.tag == 'Argument':
type_ = self.GetType(child.get('type'))
type_.default = child.get('default')
args.append(type_)
return args
def ParseFunction(self, id, element, functionType=Function):
'''functionType is used because a Operator is identical to a normal
function, only the type of the function changes.'''
name = element.get('name')
returns = self.GetType(element.get('returns'))
namespace = self.GetDecl(element.get('context'))
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
function = functionType(name, namespace, returns, params)
function.location = location
self.AddDecl(function)
self.Update(id, function)
def ParseOperatorFunction(self, id, element):
self.ParseFunction(id, element, Operator)
def GetBases(self, bases):
'Parses the string "bases" from the xml into a list of Base instances.'
if bases is None:
return []
bases = bases.split()
baseobjs = []
for base in bases:
# get the visibility
split = base.split(':')
if len(split) == 2:
visib = split[0]
base = split[1]
else:
visib = Scope.public
decl = self.GetDecl(base)
baseobj = Base(decl.FullName(), visib)
baseobjs.append(baseobj)
return baseobjs
def GetMembers(self, members):
# members must be a string with the ids of the members
if members is None:
return []
memberobjs = []
for member in members.split():
memberobjs.append(self.GetDecl(member))
return memberobjs
def ParseClass(self, id, element):
name = element.get('name')
abstract = bool(int(element.get('abstract', '0')))
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
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
self.Update(id, class_)
# now we can get the members
class_.members = self.GetMembers(element.get('members'))
def ParseStruct(self, id, element):
self.ParseClass(id, element)
def ParseFundamentalType(self, id, element):
name = element.get('name')
type_ = FundamentalType(name)
self.Update(id, type_)
def ParseArrayType(self, id, element):
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)
def ParseReferenceType(self, id, element):
type_ = self.GetType(element.get('type'))
expand = not isinstance(type_, FunctionType)
ref = ReferenceType(type_.name, type_.const, None, expand)
self.Update(id, ref)
def ParsePointerType(self, id, element):
type_ = self.GetType(element.get('type'))
expand = not isinstance(type_, FunctionType)
ref = PointerType(type_.name, type_.const, None, expand)
self.Update(id, ref)
def ParseFunctionType(self, id, element):
result = self.GetType(element.get('returns'))
args = self.GetArguments(element)
func = FunctionType(result, args)
self.Update(id, func)
def ParseMethodType(self, id, element):
class_ = self.GetDecl(element.get('basetype')).FullName()
result = self.GetType(element.get('returns'))
args = self.GetArguments(element)
method = MethodType(result, args, class_)
self.Update(id, method)
def ParseField(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
classname = self.GetDecl(element.get('context')).FullName()
type_ = self.GetType(element.get('type'))
static = bool(int(element.get('extern', '0')))
location = self.GetLocation(element.get('location'))
var = ClassVariable(type_, name, classname, visib, static)
var.location = location
self.Update(id, var)
def ParseMethod(self, id, element, methodType=Method):
name = element.get('name')
result = self.GetType(element.get('returns'))
classname = self.GetDecl(element.get('context')).FullName()
visib = element.get('access', Scope.public)
static = bool(int(element.get('static', '0')))
virtual = bool(int(element.get('virtual', '0')))
abstract = bool(int(element.get('pure_virtual', '0')))
const = bool(int(element.get('const', '0')))
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
method = methodType(
name, classname, result, params, visib, virtual, abstract, static, const)
method.location = location
self.Update(id, method)
def ParseOperatorMethod(self, id, element):
self.ParseMethod(id, element, ClassOperator)
def ParseConstructor(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
classname = self.GetDecl(element.get('context')).FullName()
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
ctor = Constructor(name, classname, params, visib)
ctor.location = location
self.Update(id, ctor)
def ParseDestructor(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
classname = self.GetDecl(element.get('context')).FullName()
virtual = bool(int(element.get('virtual', '0')))
location = self.GetLocation(element.get('location'))
des = Destructor(name, classname, visib, virtual)
des.location = location
self.Update(id, des)
def ParseConverter(self, id, element):
self.ParseMethod(id, element, ConverterOperator)
def ParseTypedef(self, id, element):
name = element.get('name')
type = self.GetDecl(element.get('type'))
context = self.GetDecl(element.get('context'))
if isinstance(context, Class):
context = context.FullName()
typedef = Typedef(type, name, context)
self.Update(id, typedef)
self.AddDecl(typedef)
def ParseEnumeration(self, id, element):
name = element.get('name')
location = self.GetLocation(element.get('location'))
context = self.GetDecl(element.get('context'))
if isinstance(context, Class):
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':
name = child.get('name')
value = int(child.get('init'))
enum.values[name] = value
self.Update(id, enum)
def ParseUnimplemented(self, id, element):
'No idea of what this is'
self.Update(id, Declaration('', ''))
def ParseUnion(self, id, element):
self.Update(id, Declaration(element.get('name'), ''))
def ParseDeclarations(filename):
'Returns a list of the top declarations found in the gcc_xml file.'
parser = GCCXMLParser()
parser.Parse(filename)
return parser.Declarations()

View File

@@ -1,67 +0,0 @@
from Exporter import Exporter
from ClassExporter import ClassExporter
from FunctionExporter import FunctionExporter
from EnumExporter import EnumExporter
from infos import *
from declarations import *
import os.path
import exporters
#==============================================================================
# HeaderExporter
#==============================================================================
class HeaderExporter(Exporter):
'Exports all declarations found in the given header'
def __init__(self, info, parser_tail=None):
Exporter.__init__(self, info, parser_tail)
def WriteInclude(self, codeunit):
pass
def SetDeclarations(self, declarations):
def IsInternalName(name):
'''Returns true if the given name looks like a internal compiler
structure'''
return name.startswith('__')
Exporter.SetDeclarations(self, declarations)
header = os.path.normpath(self.parser_header)
for decl in declarations:
# check if this declaration is in the header
location = os.path.normpath(decl.location[0])
if location != header or IsInternalName(decl.name):
continue
# ok, check the type of the declaration and export it accordingly
self.HandleDeclaration(decl)
def HandleDeclaration(self, decl):
'''Dispatch the declaration to the appropriate method, that must create
a suitable info object for a Exporter, create a Exporter, set its
declarations and append it to the list of exporters.
'''
dispatch_table = {
Class : ClassExporter,
Enumeration : EnumExporter,
Function : FunctionExporter,
}
for decl_type, exporter_type in dispatch_table.items():
if type(decl) == decl_type:
self.HandleExporter(decl, exporter_type)
break
def HandleExporter(self, decl, exporter_type):
info = self.info[decl.name]
info.name = decl.FullName()
info.include = self.info.include
exporter = exporter_type(info)
exporter.SetDeclarations(self.declarations)
exporters.exporters.append(exporter)

View File

@@ -1,19 +0,0 @@
import os.path
from Exporter import Exporter
#==============================================================================
# IncludeExporter
#==============================================================================
class IncludeExporter(Exporter):
'''Writes an include declaration to the module. Useful to add extra code
for use in the Wrappers.
This class just reimplements the Parse method to do nothing: the
WriteInclude in Exporter already does the work for us.
'''
def __init__(self, info, parser_tail=None):
Exporter.__init__(self, info, parser_tail)
def Parse(self, parser):
pass

View File

@@ -1,452 +0,0 @@
'''
Module declarations
Defines classes that represent declarations found in C++ header files.
'''
class Declaration(object):
'Represents a basic declaration.'
def __init__(self, name, namespace):
# the declaration name
self.name = name
# all the namespaces, separated by '::' = 'boost::inner'
self.namespace = namespace
# tuple (filename, line)
self.location = '', -1
def FullName(self):
'Returns the full qualified name: "boost::inner::Test"'
namespace = self.namespace or ''
#if not namespace:
# namespace = ''
if namespace and not namespace.endswith('::'):
namespace += '::'
return namespace + self.name
def __repr__(self):
return '<Declaration %s at %s>' % (self.FullName(), id(self))
def __str__(self):
return 'Declaration of %s' % self.FullName()
class Class(Declaration):
'The declaration of a class or struct.'
def __init__(self, name, namespace, members, abstract, bases):
Declaration.__init__(self, name, namespace)
# list of members
self.members = members
# whatever the class has any abstract methods
self.abstract = abstract
# instances of Base
self.bases = bases
self._members_count = {}
def __iter__(self):
return iter(self.members)
def IsAbstract(self):
'Returns True if any method of this class is abstract'
for member in self.members:
if isinstance(member, Method):
if member.abstract:
return True
return False
def RawName(self):
'Returns the raw name of a template class. name = Foo<int>, raw = Foo'
lesspos = self.name.find('<')
if lesspos != -1:
return self.name[:lesspos]
else:
return self.name
def Constructors(self, publics_only=True):
constructors = []
for member in self:
if isinstance(member, Constructor):
if publics_only and member.visibility != Scope.public:
continue
constructors.append(member)
return constructors
def HasCopyConstructor(self):
for cons in self.Constructors():
if cons.IsCopy():
return True
return False
def HasDefaultConstructor(self):
for cons in self.Constructors():
if cons.IsDefault():
return True
return False
def IsUnique(self, member_name):
if not self._members_count:
for m in self:
self._members_count[m.name] = self._members_count.get(m.name, 0) + 1
try:
return self._members_count[member_name] == 1
except KeyError:
print self._members_count
print 'Key', member_name
class NestedClass(Class):
'The declaration of a class/struct inside another class/struct.'
def __init__(self, name, class_, visib, members, abstract, bases):
Class.__init__(self, name, None, members, abstract, bases)
self.class_ = class_
self.visibility = visib
def FullName(self):
return '%s::%s' % (self.class_, self.name)
class Base:
'Represents a base class of another class.'
def __init__(self, name, visibility=None):
# class_ is the full name of the base class
self.name = name
# visibility of the derivation
if visibility is None:
visibility = Scope.public
self.visibility = visibility
class Scope:
public = 'public'
private = 'private'
protected = 'protected'
class Function(Declaration):
'The declaration of a function.'
def __init__(self, name, namespace, result, params):
Declaration.__init__(self, name, namespace)
# the result type: instance of Type, or None (constructors)
self.result = result
# the parameters: instances of Type
self.parameters = params
def PointerDeclaration(self):
'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())
def _MinArgs(self):
min = 0
for arg in self.parameters:
if arg.default is None:
min += 1
return min
minArgs = property(_MinArgs)
def _MaxArgs(self):
return len(self.parameters)
maxArgs = property(_MaxArgs)
class Operator(Function):
'The declaration of a custom operator.'
def FullName(self):
namespace = self.namespace or ''
if not namespace.endswith('::'):
namespace += '::'
return namespace + 'operator' + self.name
class Method(Function):
'The declaration of a method.'
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const):
Function.__init__(self, name, None, result, params)
self.visibility = visib
self.virtual = virtual
self.abstract = abstract
self.static = static
self.class_ = class_
self.const = const
def FullName(self):
return self.class_ + '::' + self.name
def PointerDeclaration(self):
'returns a declaration of a pointer to this function'
result = self.result.FullName()
params = ', '.join([x.FullName() for x in self.parameters])
const = ''
if self.const:
const = 'const'
return '(%s (%s::*)(%s) %s)%s' %\
(result, self.class_, params, const, self.FullName())
class Constructor(Method):
'A constructor of a class.'
def __init__(self, name, class_, params, visib):
Method.__init__(self, name, class_, None, params, visib, False, False, False, False)
def IsDefault(self):
return len(self.parameters) == 0
def IsCopy(self):
if len(self.parameters) != 1:
return False
param = self.parameters[0]
class_as_param = self.parameters[0].name == self.class_
param_reference = isinstance(param, ReferenceType)
return param_reference and class_as_param and param.const
class Destructor(Method):
'The destructor of a class.'
def __init__(self, name, class_, visib, virtual):
Method.__init__(self, name, class_, None, [], visib, virtual, False, False, False)
def FullName(self):
return self.class_ + '::~' + self.name
class ClassOperator(Method):
'The declaration of a custom operator in a class.'
def FullName(self):
return self.class_ + '::operator ' + self.name
class ConverterOperator(ClassOperator):
'An operator in the form "operator OtherClass()".'
def FullName(self):
return self.class_ + '::operator ' + self.result.name
class Type(Declaration):
'Represents a type.'
def __init__(self, name, const=False, default=None):
Declaration.__init__(self, name, None)
# whatever the type is constant or not
self.const = const
# used when the Type is a function argument
self.default = default
self.volatile = False
def __repr__(self):
if self.const:
const = 'const '
else:
const = ''
return '<Type ' + const + self.name + '>'
def FullName(self):
if self.const:
const = 'const '
else:
const = ''
return const + self.name
class ArrayType(Type):
'Represents an array.'
def __init__(self, name, min, max, const=False):
'min and max can be None.'
Type.__init__(self, name, const)
self.min = min
self.max = max
class ReferenceType(Type):
'A reference type.'
def __init__(self, name, const=False, default=None, expandRef=True):
Type.__init__(self, name, const, default)
self.expand = expandRef
def FullName(self):
'expand is False for function pointers'
expand = ' &'
if not self.expand:
expand = ''
return Type.FullName(self) + expand
class PointerType(Type):
'A pointer type.'
def __init__(self, name, const=False, default=None, expandPointer=False):
Type.__init__(self, name, const, default)
self.expand = expandPointer
def FullName(self):
'expand is False for function pointer'
expand = ' *'
if not self.expand:
expand = ''
return Type.FullName(self) + expand
class FundamentalType(Type):
'One of the fundamental types (int, void...).'
def __init__(self, name, const=False):
Type.__init__(self, name, const)
class FunctionType(Type):
'A pointer to a function.'
def __init__(self, result, params):
Type.__init__(self, '', False)
self.result = result
self.parameters = params
self.name = self.FullName()
def FullName(self):
full = '%s (*)' % self.result.FullName()
params = [x.FullName() for x in self.parameters]
full += '(%s)' % ', '.join(params)
return full
class MethodType(FunctionType):
'A pointer to a member function of a class.'
def __init__(self, result, params, class_):
Type.__init__(self, '', False)
self.result = result
self.parameters = params
self.class_ = class_
self.name = self.FullName()
def FullName(self):
full = '%s (%s::*)' % (self.result.FullName(), self.class_)
params = [x.FullName() for x in self.parameters]
full += '(%s)' % ', '.join(params)
return full
class Variable(Declaration):
'Represents a global variable.'
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
# instance of Type
self.type = type
class ClassVariable(Variable):
'Represents a class variable.'
def __init__(self, type, name, class_, visib, static):
Variable.__init__(self, type, name, None)
self.visibility = visib
self.static = static
self.class_ = class_
def FullName(self):
return self.class_ + '::' + self.name
class Enumeration(Declaration):
def __init__(self, name, namespace):
Declaration.__init__(self, name, namespace)
self.values = {} # dict of str => int
def ValueFullName(self, name):
assert name in self.values
namespace = self.namespace
if namespace:
namespace += '::'
return namespace + name
class ClassEnumeration(Enumeration):
def __init__(self, name, class_, visib):
Enumeration.__init__(self, name, None)
self.class_ = class_
self.visibility = visib
def FullName(self):
return '%s::%s' % (self.class_, self.name)
def ValueFullName(self, name):
assert name in self.values
return '%s::%s' % (self.class_, name)
class Typedef(Declaration):
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
self.type = type
self.visibility = Scope.public

View File

@@ -1,7 +0,0 @@
from __future__ import generators
def enumerate(seq):
i = 0
for x in seq:
yield i, x
i += 1

View File

@@ -1,3 +0,0 @@
# a list of Exporter instances
exporters = []

View File

@@ -1,26 +0,0 @@
'''
Various helpers for interface files.
'''
from settings import *
#==============================================================================
# FunctionWrapper
#==============================================================================
class FunctionWrapper(object):
'''Holds information about a wrapper for a function or a method. It is in 2
parts: the name of the Wrapper, and its code. The code is placed in the
declaration section of the module, while the name is used to def' the
function or method (with the pyste namespace prepend to it). If code is None,
the name is left unchanged.
'''
def __init__(self, name, code=None):
self.name = name
self.code = code
def FullName(self):
if self.code:
return namespaces.pyste + self.name
else:
return self.name

View File

@@ -1,187 +0,0 @@
import os.path
import copy
import exporters
from ClassExporter import ClassExporter
from FunctionExporter import FunctionExporter
from IncludeExporter import IncludeExporter
from EnumExporter import EnumExporter
from HeaderExporter import HeaderExporter
from exporterutils import FunctionWrapper
#==============================================================================
# DeclarationInfo
#==============================================================================
class DeclarationInfo:
def __init__(self, otherInfo=None):
self.__infos = {}
self.__attributes = {}
if otherInfo is not None:
self.__infos = copy.deepcopy(otherInfo.__infos)
self.__attributes = copy.deepcopy(otherInfo.__attributes)
def __getitem__(self, name):
'Used to access sub-infos'
if name.startswith('__'):
raise AttributeError
default = DeclarationInfo()
default._Attribute('name', name)
return self.__infos.setdefault(name, default)
def __getattr__(self, name):
return self[name]
def _Attribute(self, name, value=None):
if value is None:
# get value
return self.__attributes.get(name)
else:
# set value
self.__attributes[name] = value
#==============================================================================
# FunctionInfo
#==============================================================================
class FunctionInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherOption=None):
DeclarationInfo.__init__(self, otherOption)
self._Attribute('name', name)
self._Attribute('include', include)
# create a FunctionExporter
exporter = FunctionExporter(InfoWrapper(self), tail)
exporters.exporters.append(exporter)
#==============================================================================
# ClassInfo
#==============================================================================
class ClassInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherInfo=None):
DeclarationInfo.__init__(self, otherInfo)
self._Attribute('name', name)
self._Attribute('include', include)
# create a ClassExporter
exporter = ClassExporter(InfoWrapper(self), tail)
exporters.exporters.append(exporter)
#==============================================================================
# IncludeInfo
#==============================================================================
class IncludeInfo(DeclarationInfo):
def __init__(self, include):
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = IncludeExporter(InfoWrapper(self))
exporters.exporters.append(exporter)
#==============================================================================
# templates
#==============================================================================
def GenerateName(name, type_list):
name = name.replace('::', '_')
names = [name] + type_list
return '_'.join(names)
class ClassTemplateInfo(DeclarationInfo):
def __init__(self, name, include):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
def Instantiate(self, type_list, rename=None):
if not rename:
rename = GenerateName(self._Attribute('name'), type_list)
# generate code to instantiate the template
types = ', '.join(type_list)
tail = 'typedef %s< %s > %s;\n' % (self._Attribute('name'), types, rename)
tail += 'void __instantiate_%s()\n' % rename
tail += '{ sizeof(%s); }\n\n' % rename
# create a ClassInfo
class_ = ClassInfo(rename, self._Attribute('include'), tail, self)
return class_
def __call__(self, types, rename=None):
if isinstance(types, str):
types = types.split()
return self.Instantiate(types, rename)
#==============================================================================
# EnumInfo
#==============================================================================
class EnumInfo(DeclarationInfo):
def __init__(self, name, include):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
exporter = EnumExporter(InfoWrapper(self))
exporters.exporters.append(exporter)
#==============================================================================
# HeaderInfo
#==============================================================================
class HeaderInfo(DeclarationInfo):
def __init__(self, include):
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = HeaderExporter(InfoWrapper(self))
exporters.exporters.append(exporter)
#==============================================================================
# InfoWrapper
#==============================================================================
class InfoWrapper:
'Provides a nicer interface for a info'
def __init__(self, info):
self.__dict__['_info'] = info # so __setattr__ is not called
def __getitem__(self, name):
return InfoWrapper(self._info[name])
def __getattr__(self, name):
return self._info._Attribute(name)
def __setattr__(self, name, value):
self._info._Attribute(name, value)
#==============================================================================
# Functions
#==============================================================================
def exclude(option):
option._Attribute('exclude', True)
def set_policy(option, policy):
option._Attribute('policy', policy)
def rename(option, name):
option._Attribute('rename', name)
def set_wrapper(option, wrapper):
if isinstance(wrapper, str):
wrapper = FunctionWrapper(wrapper)
option._Attribute('wrapper', wrapper)
def instantiate(template, types, rename=None):
if isinstance(types, str):
types = types.split()
return template.Instantiate(types, rename)

View File

@@ -1,75 +0,0 @@
class Policy:
'Represents one of the call policies of boost.python.'
def __init__(self):
raise RuntimeError, "Can't create an instance of the class Policy"
def Code(self):
'Returns the string corresponding to a instancialization of the policy.'
pass
def _next(self):
if self.next is not None:
return ', %s >' % self.next.Code()
else:
return ' >'
class return_internal_reference(Policy):
'Ties the return value to one of the parameters.'
def __init__(self, param=1, next=None):
'''
param is the position of the parameter, or None for "self".
next indicates the next policy, or None.
'''
self.param = param
self.next=next
def Code(self):
c = 'return_internal_reference< %i' % self.param
c += self._next()
return c
class with_custodian_and_ward(Policy):
'Ties lifetime of two arguments of a function.'
def __init__(self, custodian, ward, next=None):
self.custodian = custodian
self.ward = ward
self.next = next
def Code(self):
c = 'with_custodian_and_ward< %i, %i' % (self.custodian, self.ward)
c += self._next()
return c
class return_value_policy(Policy):
'Policy to convert return values.'
def __init__(self, which, next=None):
self.which = which
self.next = next
def Code(self):
c = 'return_value_policy< %s' % self.which
c += self._next()
return c
# values for return_value_policy
reference_existing_object = 'reference_existing_object'
copy_const_reference = 'copy_const_reference'
copy_non_const_reference = 'copy_non_const_reference'
manage_new_object = 'manage_new_object'

View File

@@ -1,17 +0,0 @@
import profile
import pstats
import pyste
import psyco
import elementtree.XMLTreeBuilder as XMLTreeBuilder
import GCCXMLParser
if __name__ == '__main__':
#psyco.bind(XMLTreeBuilder.fixtext)
#psyco.bind(XMLTreeBuilder.fixname)
#psyco.bind(XMLTreeBuilder.TreeBuilder)
#psyco.bind(GCCXMLParser.GCCXMLParser)
profile.run('pyste.Main()', 'profile')
p = pstats.Stats('profile')
p.strip_dirs().sort_stats(-1).print_stats()

View File

@@ -1,154 +0,0 @@
'''
Usage:
pyste [options] --module=<name> interface-files
where options are:
-I <path> add an include path
-D <symbol> define symbol
--no-using do not declare "using namespace boost";
use explicit declarations instead
--pyste-ns=<name> set the namespace where new types will be declared;
default is "pyste"
'''
import sys
import os
import getopt
import exporters
import CodeUnit
import infos
import exporterutils
import settings
from policies import *
from CppParser import CppParser, CppParserError
from Exporter import Exporter
from FunctionExporter import FunctionExporter
from ClassExporter import ClassExporter
from IncludeExporter import IncludeExporter
from HeaderExporter import HeaderExporter
def GetDefaultIncludes():
if 'INCLUDE' in os.environ:
include = os.environ['INCLUDE']
return include.split(os.pathsep)
else:
return []
def ParseArguments():
def Usage():
print __doc__
sys.exit(1)
options, files = getopt.getopt(sys.argv[1:], 'I:D:', ['module=', 'out=', 'no-using', 'pyste-ns=', 'debug'])
includes = GetDefaultIncludes()
defines = []
module = None
out = None
for opt, value in options:
if opt == '-I':
includes.append(value)
elif opt == '-D':
defines.append(value)
elif opt == '--module':
module = value
elif opt == '--out':
out = value
elif opt == '--no-using':
settings.namespaces.python = 'boost::python::'
CodeUnit.CodeUnit.USING_BOOST_NS = False
elif opt == '--pyste-ns':
settings.namespaces.pyste = value + '::'
elif opt == '--debug':
settings.DEBUG = True
else:
print 'Unknown option:', opt
Usage()
if not files or not module:
Usage()
if not out:
out = module + '.cpp'
return includes, defines, module, out, files
def CreateContext():
'create the context where a interface file can be executed'
context = {}
# infos
context['Function'] = infos.FunctionInfo
context['Class'] = infos.ClassInfo
context['Include'] = infos.IncludeInfo
context['Template'] = infos.ClassTemplateInfo
context['Enum'] = infos.EnumInfo
context['AllFromHeader'] = infos.HeaderInfo
# functions
context['rename'] = infos.rename
context['set_policy'] = infos.set_policy
context['exclude'] = infos.exclude
context['set_wrapper'] = infos.set_wrapper
# policies
context['return_internal_reference'] = return_internal_reference
context['with_custodian_and_ward'] = with_custodian_and_ward
context['return_value_policy'] = return_value_policy
context['reference_existing_object'] = reference_existing_object
context['copy_const_reference'] = copy_const_reference
context['copy_non_const_reference'] = copy_non_const_reference
context['manage_new_object'] = manage_new_object
# utils
context['Wrapper'] = exporterutils.FunctionWrapper
return context
def Main():
includes, defines, module, out, interfaces = ParseArguments()
# execute the interface files
for interface in interfaces:
context = CreateContext()
execfile(interface, context)
# parse all the C++ code
parser = CppParser(includes, defines)
exports = exporters.exporters[:]
for export in exports:
try:
export.Parse(parser)
except CppParserError, e:
print '\n'
print '***', e, ': exitting'
return 2
print
# sort the exporters by its order
exports = [(x.Order(), x) for x in exporters.exporters]
exports.sort()
exports = [x for _, x in exports]
# now generate the wrapper code
codeunit = CodeUnit.CodeUnit(module)
exported_names = []
for export in exports:
export.GenerateCode(codeunit, exported_names)
exported_names.append(export.Name())
codeunit.Save(out)
print 'Module %s generated' % module
return 0
def UsePsyco():
'Tries to use psyco if it is installed'
try:
import psyco
import elementtree.XMLTreeBuilder as XMLTreeBuilder
import GCCXMLParser
psyco.bind(XMLTreeBuilder.fixtext)
psyco.bind(XMLTreeBuilder.fixname)
psyco.bind(XMLTreeBuilder.TreeBuilder)
psyco.bind(GCCXMLParser.GCCXMLParser)
except ImportError: pass
if __name__ == '__main__':
UsePsyco()
status = Main()
sys.exit(status)

View File

@@ -1,12 +0,0 @@
#==============================================================================
# Global information
#==============================================================================
DEBUG = False
class namespaces:
boost = 'boost::'
pyste = ''
python = '' # default is to not use boost::python namespace explicitly, so
# use the "using namespace" statement instead

3
pyste/tests/.cvsignore Normal file
View File

@@ -0,0 +1,3 @@
*.pyc
*.dll
*.cpp

View File

@@ -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):

View File

@@ -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())

View File

@@ -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 ;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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
View 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
View 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])

View File

@@ -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>

View File

@@ -15,9 +15,6 @@
>>> (-y).value()
39
>>> (x + y).value()
3
>>> abs(y).value()
39

View File

@@ -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.

View File

@@ -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.

View File

@@ -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>

View File

@@ -95,8 +95,53 @@ shared_ptr<Y> factory(int n)
static int stored_v() { return functions<Z>::get()->v(); }
static shared_ptr<Z> stored_z() { return functions<Z>::get(); }
// regressions from Nicodemus
struct A
{
virtual int f() = 0;
static int call_f(shared_ptr<A>& a) { return a->f(); }
};
struct B: A
{
int f() { return 1; }
};
boost::shared_ptr<A> New(bool make)
{
return boost::shared_ptr<A>( make ? new B() : 0 );
}
struct A_Wrapper: A
{
A_Wrapper(PyObject* self_):
A(), self(self_) {}
int f() {
return call_method< int >(self, "f");
}
PyObject* self;
};
// ------
BOOST_PYTHON_MODULE(shared_ptr_ext)
{
class_<A, boost::shared_ptr<A_Wrapper>, boost::noncopyable>("A")
.def("call_f", &A::call_f)
.staticmethod("call_f")
;
// This is the ugliness required to register a to-python converter
// for shared_ptr<A>.
objects::class_value_wrapper<
shared_ptr<A>
, objects::make_ptr_instance<A, objects::pointer_holder<shared_ptr<A>,A> >
>();
def("New", &New);
class_<X, boost::noncopyable>("X", init<int>())
.def("value", &X::value)
;

View File

@@ -1,6 +1,11 @@
'''
>>> from shared_ptr_ext import *
>>> a = New(1)
>>> A.call_f(a)
1
>>> New(0)
>>> type(factory(3))
<class 'shared_ptr_ext.Y'>
>>> type(factory(42))

View File

@@ -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>