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

Remove a bunch of obsolete files.

This commit is contained in:
Stefan Seefeld
2016-09-29 23:18:00 -04:00
parent 061050c006
commit 482219f20a
131 changed files with 0 additions and 9171 deletions

Binary file not shown.

View File

@@ -1,28 +0,0 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/object.hpp>
#include <boost/python/class.hpp>
using namespace boost::python;
struct X
{
int x;
X(int n) : x(n) { }
};
int x_function(X& x)
{ return x.x;
}
BOOST_PYTHON_MODULE(class_ext)
{
class_<X>("X", init<int>());
def("x_function", x_function);
}
#include "module_tail.cpp"

View File

@@ -1,12 +0,0 @@
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/index.html">
</head>
<body>
Automatically loading index page... if nothing happens, please go to
<a href="doc/index.html">doc/index.html</a>.
</body>
</html>

View File

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

View File

@@ -1,35 +0,0 @@
.. Copyright Bruno da Silva de Oliveira 2006. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Pyste - Python Semi-Automatic Exporter
======================================
Pyste is a Boost.Python code generator. The user specifies the classes and
functions to be exported using a simple interface file, which following the
Boost.Python's philosophy, is simple Python code. Pyste then uses GCCXML to
parse all the headers and extract the necessary information to automatically
generate C++ code.
The documentation can be found in the file index.html accompaning this README.
Enjoy!
Bruno da Silva de Oliveira (nicodemus@esss.com.br)
Thanks
======
- David Abrahams, creator of Boost.Python, for tips on the syntax of the interface
file and support.
- Marcelo Camelo, for design tips, support and inspiration for this project.
Also, the name was his idea. 8)
- Brad King, creator of the excellent GCCXML (http://www.gccxml.org)
- Fredrik Lundh, creator of the elementtree library (http://effbot.org)
Bugs
====
Pyste is a young tool, so please help it to get better! Send bug reports to
nicodemus@esss.com.br, accompaining the stack trace in case of exceptions.
If possible, run pyste with --debug, and send the resulting xmls too (pyste
will output a xml file with the same of each header it parsed).

View File

@@ -1,18 +0,0 @@
.. Copyright Bruno da Silva de Oliveira 2006. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- Make Pyste accept already-generated xml files
- throw() declaration in virtual wrapper's member functions
- Allow protected methods to be overriden in Python
- Expose programmability to the Pyste files (listing members of a class, for
instance)
- Virtual operators
- args() support
- set policies to methods with the same name

View File

@@ -1,55 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import os
import sys
import shutil
import fnmatch
from zipfile import ZipFile, ZIP_DEFLATED
def findfiles(directory, mask):
def visit(files, dir, names):
for name in names:
if fnmatch.fnmatch(name, mask):
files.append(os.path.join(dir, name))
files = []
os.path.walk(directory, visit, files)
return files
def main():
# test if PyXML is installed
try:
import _xmlplus.parsers.expat
pyxml = '--includes _xmlplus.parsers.expat'
except ImportError:
pyxml = ''
# create exe
status = os.system('python setup.py py2exe %s >& build.log' % pyxml)
if status != 0:
raise RuntimeError, 'Error creating EXE'
# create distribution
import pyste
version = pyste.__VERSION__
zip = ZipFile('pyste-%s.zip' % version, 'w', ZIP_DEFLATED)
# include the base files
dist_dir = 'dist/pyste'
for basefile in os.listdir(dist_dir):
zip.write(os.path.join(dist_dir, basefile), os.path.join('pyste', basefile))
# include documentation
for doc_file in findfiles('../doc', '*.*'):
dest_name = os.path.join('pyste/doc', doc_file[3:])
zip.write(doc_file, dest_name)
zip.write('../index.html', 'pyste/doc/index.html')
zip.close()
# cleanup
os.remove('build.log')
shutil.rmtree('build')
shutil.rmtree('dist')
if __name__ == '__main__':
sys.path.append('../src')
main()

10
pyste/dist/setup.py vendored
View File

@@ -1,10 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
from distutils.core import setup
import py2exe
import sys
sys.path.append('../src')
setup(name='pyste', scripts=['../src/pyste.py'])

View File

@@ -1,79 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Adding New Methods</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="global_variables.html">
<link rel="next" href="inserting_code.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Adding New Methods</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="global_variables.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="inserting_code.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Suppose that you want to add a function to a class, turning it into a member
function:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</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>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=identifier>World</span><span class=special>&amp; </span><span class=identifier>w</span><span class=special>)
{
</span><span class=keyword>return </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>msg</span><span class=special>;
}
</span></pre></code>
<p>
Here, we want to make <tt>greet</tt> work as a member function of the class <tt>World</tt>. We do
that using the <tt>add_method</tt> construct:</p>
<code><pre>
<span class=identifier>W </span><span class=special>= </span><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>add_method</span><span class=special>(</span><span class=identifier>W</span><span class=special>, </span><span class=string>&quot;greet&quot;</span><span class=special>)
</span></pre></code>
<p>
Notice also that then you can rename it, set its policy, just like a regular
member function:</p>
<code><pre>
<span class=identifier>rename</span><span class=special>(</span><span class=identifier>W</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=literal>'Greet'</span><span class=special>)
</span></pre></code>
<p>
Now from Python:</p>
<code><pre>
<span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>hello
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>w </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>()
&gt;&gt;&gt; </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>set</span><span class=special>(</span><span class=literal>'Ni'</span><span class=special>)
&gt;&gt;&gt; </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
</span><span class=literal>'Ni'
</span><span class=special>&gt;&gt;&gt; </span><span class=identifier>print </span><span class=literal>'Oh no! The knights who say Ni!'
</span><span class=identifier>Oh </span><span class=identifier>no</span><span class=special>! </span><span class=identifier>The </span><span class=identifier>knights </span><span class=identifier>who </span><span class=identifier>say </span><span class=identifier>Ni</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="global_variables.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="inserting_code.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,85 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Exporting An Entire Header</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="wrappers.html">
<link rel="next" href="smart_pointers.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Exporting An Entire 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"><a href="smart_pointers.html"><img src="theme/r_arr.gif" border="0"></a></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 width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <b>AllFromHeader is broken</b> in some cases. Until it is fixed,
use at you own risk.
</td>
</tr>
</table>
<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"><a href="smart_pointers.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,49 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Global Variables</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="smart_pointers.html">
<link rel="next" href="adding_new_methods.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Global Variables</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="smart_pointers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="adding_new_methods.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
To export global variables, use the <tt>Var</tt> construct:</p>
<code><pre>
<span class=identifier>Var</span><span class=special>(</span><span class=string>&quot;myglobal&quot;</span><span class=special>, </span><span class=string>&quot;foo.h&quot;</span><span class=special>)
</span></pre></code>
<p>
Beware of non-const global variables: changes in Python won't reflect in C++!
If you really must change them in Python, you will have to write some accessor
functions, and export those.</p>
<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="smart_pointers.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="adding_new_methods.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,72 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Inserting Code</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="adding_new_methods.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Inserting Code</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="adding_new_methods.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>
You can insert arbitrary code in the generated cpps, just use the functions
<tt>declaration_code</tt> and <tt>module_code</tt>. This will insert the given string in the
respective sections. Example:</p>
<code><pre>
##<span class=identifier>file </span><span class=identifier>A</span><span class=special>.</span><span class=identifier>pyste
</span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;A&quot;</span><span class=special>, </span><span class=string>&quot;A.h&quot;</span><span class=special>)
</span><span class=identifier>declaration_code</span><span class=special>(</span><span class=string>&quot;/* declaration_code() comes here */\n&quot;</span><span class=special>)
</span><span class=identifier>module_code</span><span class=special>(</span><span class=string>&quot;/* module_code() comes here */\n&quot;</span><span class=special>)
</span></pre></code>
<p>
Will generate:</p>
<code><pre>
<span class=comment>// Includes ====================================================================
</span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
// </span><span class=identifier>Using </span><span class=special>=======================================================================
</span><span class=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
// </span><span class=identifier>Declarations </span><span class=special>================================================================
/* </span><span class=identifier>declaration_code</span><span class=special>() </span><span class=identifier>comes </span><span class=identifier>here </span><span class=special>*/
// </span><span class=identifier>Module </span><span class=special>======================================================================
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>A</span><span class=special>)
{
</span><span class=identifier>class_</span><span class=special>&lt; </span><span class=identifier>A </span><span class=special>&gt;(</span><span class=string>&quot;A&quot;</span><span class=special>, </span><span class=identifier>init</span><span class=special>&lt; &gt;())
.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>init</span><span class=special>&lt; </span><span class=keyword>const </span><span class=identifier>A</span><span class=special>&amp; &gt;())
;
/* </span><span class=identifier>module_code</span><span class=special>() </span><span class=identifier>comes </span><span class=identifier>here </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="adding_new_methods.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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,73 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Introduction</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="next" href="running_pyste.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Introduction</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"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="running_pyste.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<a name="what_is_pyste_"></a><h2>What is Pyste?</h2><p>
Pyste is a <a href="../../index.html">
Boost.Python</a> code generator. The user specifies the classes and
functions to be exported using a simple <i>interface file</i>, which following the
<a href="../../index.html">
Boost.Python</a>'s philosophy, is simple Python code. Pyste then uses <a href="http://www.gccxml.org">
GCCXML</a> to
parse all the headers and extract the necessary information to automatically
generate C++ code.</p>
<a name="example"></a><h2>Example</h2><p>
Let's borrow the class <tt>World</tt> from the <a href="../../doc/tutorial/doc/html/python/exposing.html">
tutorial</a>: </p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>World
</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></pre></code>
<p>
Here's the interface file for it, named <tt>world.pyste</tt>:</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;world.h&quot;</span><span class=special>)
</span></pre></code>
<p>
and that's it!</p>
<p>
The next step is invoke Pyste in the command-line:</p>
<code><pre>python pyste.py --module=hello world.pyste</pre></code><p>
this will create a file &quot;<tt>hello.cpp</tt>&quot; in the directory where the command was
run. </p>
<p>
Pyste supports the following features:</p>
<ul><li>Functions</li><li>Classes</li><li>Class Templates</li><li>Virtual Methods</li><li>Overloading</li><li>Attributes </li><li>Enums (both &quot;free&quot; enums and class enums)</li><li>Nested Classes</li><li>Support for <tt>boost::shared_ptr</tt> and <tt>std::auto_ptr</tt></li><li>Global Variables</li></ul><table border="0">
<tr>
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
<td width="20"><a href="running_pyste.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,90 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Policies</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="renaming_and_excluding.html">
<link rel="next" href="templates.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Policies</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="renaming_and_excluding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="templates.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Even thought Pyste can identify various elements in the C++ code, like virtual
member functions, attributes, and so on, one thing that it can't do is to
guess the semantics of functions that return pointers or references. In this
case, the user must manually specify the policy. Policies are explained in the
<a href="../../doc/tutorial/doc/html/python/functions.html#python.call_policies">
tutorial</a>.</p>
<p>
The policies in Pyste are named exactly as in <a href="../../index.html">
Boost.Python</a>, only the syntax is
slightly different. For instance, this policy:</p>
<code><pre>
<span class=identifier>return_internal_reference</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=identifier>with_custodian_and_ward</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>&gt; &gt;()
</span></pre></code>
<p>
becomes in Pyste: </p>
<code><pre>
<span class=identifier>return_internal_reference</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=identifier>with_custodian_and_ward</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>))
</span></pre></code>
<p>
The user can specify policies for functions and virtual member functions with
the <tt>set_policy</tt> function:</p>
<code><pre>
<span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>f</span><span class=special>, </span><span class=identifier>return_internal_reference</span><span class=special>())
</span><span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>, </span><span class=identifier>return_value_policy</span><span class=special>(</span><span class=identifier>manage_new_object</span><span class=special>))
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <b>What if a function or member function needs a policy and
the user doesn't set one?</b><br><br> If a function needs a policy and one
was not set, Pyste will issue a error. The user should then go in the
interface file and set the policy for it, otherwise the generated cpp won't
compile.
</td>
</tr>
</table>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img>
Note that for functions that return <tt>const T&amp;</tt>, the policy
<tt>return_value_policy&lt;copy_const_reference&gt;()</tt> wil be used by default, because
that's normally what you want. You can change it to something else if you need
to, though.
</td>
</tr>
</table>
<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="renaming_and_excluding.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="templates.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,664 +0,0 @@
[doc Pyste Documentation]
[/ Copyright 2003 Bruno da Silva de Oliveira and Joel de Guzman.
Distributed under the Boost Software License, Version 1.0. (See
accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt) ]
[def GCCXML [@http://www.gccxml.org GCCXML]]
[def Boost.Python [@../../index.html Boost.Python]]
[page Introduction]
[h2 What is Pyste?]
Pyste is a Boost.Python code generator. The user specifies the classes and
functions to be exported using a simple ['interface file], which following the
Boost.Python's philosophy, is simple Python code. Pyste then uses GCCXML to
parse all the headers and extract the necessary information to automatically
generate C++ code.
[h2 Example]
Let's borrow the class [^World] from the [@../../doc/tutorial/doc/exposing_classes.html tutorial]:
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
Here's the interface file for it, named [^world.pyste]:
Class("World", "world.h")
and that's it!
The next step is invoke Pyste in the command-line:
[pre python pyste.py --module=hello world.pyste]
this will create a file "[^hello.cpp]" in the directory where the command was
run.
Pyste supports the following features:
* Functions
* Classes
* Class Templates
* Virtual Methods
* Overloading
* Attributes
* Enums (both "free" enums and class enums)
* Nested Classes
* Support for [^boost::shared_ptr] and [^std::auto_ptr]
* Global Variables
[page Running Pyste]
To run Pyste, you will need:
* Python 2.2, available at [@http://www.python.org python's website].
* The great [@http://effbot.org elementtree] library, from Fredrik Lundh.
* The excellent GCCXML, from Brad King.
Installation for the tools is available in their respective webpages.
[blurb
[$theme/note.gif] GCCXML must be accessible in the PATH environment variable, so
that Pyste can call it. How to do this varies from platform to platform.
]
[h2 Ok, now what?]
Well, now let's fire it up:
[pre
'''
>python pyste.py
Pyste version 0.9.26
Usage:
pyste [options] interface-files
where options are:
--module=<name> The name of the module that will be generated;
defaults to the first interface filename, without
the extension.
-I <path> Add an include path
-D <symbol> Define symbol
--multiple Create various cpps, instead of only one
(useful during development)
--out=<name> Specify output filename (default: <module>.cpp)
in --multiple mode, this will be a directory
--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 the empty namespace
--debug Writes the xml for each file parsed in the current
directory
--cache-dir=<dir> Directory for cache files (speeds up future runs)
--only-create-cache Recreates all caches (doesn't generate code).
--generate-main Generates the _main.cpp file (in multiple mode)
--file-list A file with one pyste file per line. Use as a
substitute for passing the files in the command
line.
-h, --help Print this help and exit
-v, --version Print version information
'''
]
Options explained:
The [^-I] and [^-D] are preprocessor flags, which are needed by GCCXML to parse
the header files correctly and by Pyste to find the header files declared in the
interface files.
[^--out] names the output file (default: [^<module>.cpp]), or in multiple mode,
names a output directory for the files (default: [^<module>]).
[^--no-using] tells Pyste to don't declare "[^using namespace boost;]" in the
generated cpp, using the namespace boost::python explicitly in all declarations.
Use only if you're having a name conflict in one of the files.
Use [^--pyste-ns] to change the namespace where new types are declared (for
instance, the virtual wrappers). Use only if you are having any problems. By
default, Pyste uses the empty namespace.
[^--debug] will write in the current directory a xml file as outputted by GCCXML
for each header parsed. Useful for bug reports.
[^--file-list] names a file where each line points to a Pyste file. Use this instead
to pass the pyste files if you have a lot of them and your shell has some command line
size limit.
The other options are explained below, in [@#multiple_mode [*Multiple Mode]] and
[@#cache [*Cache]].
[^-h, --help, -v, --version] are self-explaining, I believe. ;)
So, the usage is simple enough:
[pre >python pyste.py --module=mymodule file.pyste file2.pyste ...]
will generate a file [^mymodule.cpp] in the same dir where the command was
executed. Now you can compile the file using the same instructions of the
[@../../doc/tutorial/doc/building_hello_world.html tutorial].
[h2 Wait... how do I set those I and D flags?]
Don't worry: normally GCCXML is already configured correctly for your plataform,
so the search path to the standard libraries and the standard defines should
already be set. You only have to set the paths to other libraries that your code
needs, like Boost, for example.
Plus, Pyste automatically uses the contents of the environment variable
[^INCLUDE] if it exists. Visual C++ users should run the [^Vcvars32.bat] file,
which for Visual C++ 6 is normally located at:
C:\Program Files\Microsoft Visual Studio\VC98\bin\Vcvars32.bat
with that, you should have little trouble setting up the flags.
[blurb [$theme/note.gif][*A note about Psyco][br][br]
Although you don't have to install [@http://psyco.sourceforge.net/ Psyco] to
use Pyste, if you do, Pyste will make use of it to speed up the wrapper
generation. Speed ups of 30% can be achieved, so it's highly recommended.
]
[h2 Multiple Mode]
The multiple mode is useful in large projects, where the presence of multiple
classes in a single file makes the compilation unpractical (excessive memory
usage, mostly).
The solution is make Pyste generate multiple files, more specifically one cpp
file for each Pyste file. This files will contain a function named after the
file, for instance Export_MyPysteFile, which will contain all the code to export
the classes, enums, etc. You can pass as much files as you want this way:
[pre >python pyste.py --module=mymodule file1.pyste file2.pyste]
This will create the files [^mymodule/file1.cpp] and [^mymodule/file2.cpp]. You
can then later do:
[pre >python pyste.py --module=mymodule file3.pyste]
and [^mymodule/file3.cpp] will be generated.
But compiling and linking this files won't be sufficient to generate your
extension. You have to also generate a file named [^main.cpp]; call pyste with
[*all] the Pyste files of your extension, and use the [^--generate-main] option:
[pre >python pyste.py --module=mymodule --generate-main file1.pyste file2.pyste file3.pyste]
Now compile and link all this files together and your extension is ready for
use.
[h2 Cache]
Pyste now supports a form of cache, which is a way to speed up the code
generation. Most of the time that Pyste takes to generate the code comes from
having to execute GCCXML (since being a front-end to GCC, it has to compile the
header files) and reading back the XML generated.
When you use the [^--cache-dir=<dir>] option, Pyste will dump in the specified
directory the generated XMLs to a file named after the Pyste file, with the
extension [^.pystec]. The next time you run with this option, Pyste will use
the cache, instead of calling GCCXML again:
[pre >python pyste.py --module=mymodule --cache-dir=cache file1.pyste]
Will generate [^file1.cpp] and [^cache/file1.pystec]. Next time you execute
this command, the cache file will be used. Note that Pyste doesn't do any check
to ensure that the cache is up to date, but you can configure your build system to do that for you.
When you run Pyste with [^--only-create-cache], all the cache files will be
created again, but no code will be generated.
[page The Interface Files]
The interface files are the heart of Pyste. The user creates one or more
interface files declaring the classes and functions he wants to export, and then
invokes Pyste passing the interface files to it. Pyste then generates a single
cpp file with Boost.Python code, with all the classes and functions exported.
Besides declaring the classes and functions, the user has a number of other
options, like renaming e excluding classes and member functionis. Those are
explained later on.
[h2 Basics]
Suppose we have a class and some functions that we want to expose to Python
declared in the header [^hello.h]:
struct World
{
World(std::string msg): msg(msg) {}
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
enum choice { red, blue };
namespace test {
void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
}
We create a file named [^hello.pyste] and create instances of the classes
[^Function], [^Class] and [^Enum]:
Function("test::show", "hello.h")
Class("World", "hello.h")
Enum("choice", "hello.h")
That will expose the class, the free function and the enum found in [^hello.h].
[h2 Inheritance]
Pyste automatically generates the correct code (specifying [^bases<>] in the
[^class_] declaration) [*if] the Class() function that exports the base classes
and their children are in the same Pyste file. If that's not the case, you have
to indicate that there's a relationship between the Pyste files using the
[^Import] function specifying the other Pyste file.
Suppose we have two classes, [^A] and [^B], and A is a base class for B. We
create two Pyste files:
[^A.pyste]:
Class("A", "A.h")
[^B.pyste]:
Import("A.pyste")
Class("B", "B.h")
Note that we specify that [^B] needs to know about [^A] to be properly exported.
[page:1 Renaming and Excluding]
You can easily rename functions, classes, member functions, attributes, etc. Just use the
function [^rename], like this:
World = Class("World", "hello.h")
rename(World, "IWorld")
show = Function("choice", "hello.h")
rename(show, "Show")
You can rename member functions and attributes using this syntax:
rename(World.greet, "Greet")
rename(World.set, "Set")
choice = Enum("choice", "hello.h")
rename(choice.red, "Red")
rename(choice.blue, "Blue")
You can exclude functions, classes, member functions, attributes, etc, in the same way,
with the function [^exclude]:
exclude(World.greet)
exclude(World.msg)
To access the operators of a class, access the member [^operator] like this
(supposing that [^C] is a class being exported):
exclude(C.operator['+'])
exclude(C.operator['*'])
exclude(C.operator['<<'])
The string inside the brackets is the same as the name of the operator in C++.[br]
[h2 Virtual Member Functions]
Pyste automatically generates wrappers for virtual member functions, but you may
want to disable this behaviour (for performance reasons, for instance) if you do
not plan to override the functions in Python. To do this, use the function
[^final]:
C = Class('C', 'C.h')
final(C.foo) # C::foo is a virtual member function
No virtual wrapper code will be generated for the virtual member function
C::foo that way.
[page:1 Policies]
Even thought Pyste can identify various elements in the C++ code, like virtual
member functions, attributes, and so on, one thing that it can't do is to
guess the semantics of functions that return pointers or references. In this
case, the user must manually specify the policy. Policies are explained in the
[@../../doc/tutorial/doc/call_policies.html tutorial].
The policies in Pyste are named exactly as in Boost.Python, only the syntax is
slightly different. For instance, this policy:
return_internal_reference<1, with_custodian_and_ward<1, 2> >()
becomes in Pyste:
return_internal_reference(1, with_custodian_and_ward(1, 2))
The user can specify policies for functions and virtual member functions with
the [^set_policy] function:
set_policy(f, return_internal_reference())
set_policy(C.foo, return_value_policy(manage_new_object))
[blurb
[$theme/note.gif] [*What if a function or member function needs a policy and
the user doesn't set one?][br][br] If a function needs a policy and one
was not set, Pyste will issue a error. The user should then go in the
interface file and set the policy for it, otherwise the generated cpp won't
compile.
]
[blurb
[$theme/note.gif]
Note that for functions that return [^const T&], the policy
[^return_value_policy<copy_const_reference>()] wil be used by default, because
that's normally what you want. You can change it to something else if you need
to, though.
]
[page:1 Templates]
Template classes can easily be exported too, but you can't export the template
itself... you have to export instantiations of it! So, if you want to export a
[^std::vector], you will have to export vectors of int, doubles, etc.
Suppose we have this code:
template <class T>
struct Point
{
T x;
T y;
};
And we want to export [^Point]s of int and double:
Point = Template("Point", "point.h")
Point("int")
Point("double")
Pyste will assign default names for each instantiation. In this example, those
would be "[^Point_int]" and "[^Point_double]", but most of the time users will want to
rename the instantiations:
Point("int", "IPoint") // renames the instantiation
double_inst = Point("double") // another way to do the same
rename(double_inst, "DPoint")
Note that you can rename, exclude, set policies, etc, in the [^Template] object
like you would do with a [^Function] or a [^Class]. This changes affect all
[*future] instantiations:
Point = Template("Point", "point.h")
Point("float", "FPoint") // will have x and y as data members
rename(Point.x, "X")
rename(Point.y, "Y")
Point("int", "IPoint") // will have X and Y as data members
Point("double", "DPoint") // also will have X and Y as data member
If you want to change a option of a particular instantiation, you can do so:
Point = Template("Point", "point.h")
Point("int", "IPoint")
d_inst = Point("double", "DPoint")
rename(d_inst.x, "X") // only DPoint is affect by this renames,
rename(d_inst.y, "Y") // IPoint stays intact
[blurb [$theme/note.gif] [*What if my template accepts more than one type?]
[br][br]
When you want to instantiate a template with more than one type, you can pass
either a string with the types separated by whitespace, or a list of strings
'''("int double" or ["int", "double"]''' would both work).
]
[page:1 Wrappers]
Suppose you have this function:
std::vector<std::string> names();
But you don't want to [@../../doc/v2/faq.html#question2 to export std::vector<std::string>],
you want this function to return a python list of strings. Boost.Python has
excellent support for things like that:
list names_wrapper()
{
list result;
// call original function
vector<string> v = names();
// put all the strings inside the python list
vector<string>::iterator it;
for (it = v.begin(); it != v.end(); ++it){
result.append(*it);
}
return result;
}
BOOST_PYTHON_MODULE(test)
{
def("names", &names_wrapper);
}
Nice heh? Pyste supports this mechanism too. You declare the [^names_wrapper]
function in a header named "[^test_wrappers.h]" and in the interface file:
Include("test_wrappers.h")
names = Function("names", "test.h")
set_wrapper(names, "names_wrapper")
You can optionally declare the function in the interface file itself:
names_wrapper = Wrapper("names_wrapper",
"""
list names_wrapper()
{
// code to call name() and convert the vector to a list...
}
""")
names = Function("names", "test.h")
set_wrapper(names, names_wrapper)
The same mechanism can be used with member functions too. Just remember that
the first parameter of wrappers for member functions is a pointer to the
class, as in:
struct C
{
std::vector<std::string> names();
}
list names_wrapper(C* c)
{
// same as before, calling c->names() and converting result to a list
}
And then in the interface file:
C = Class("C", "test.h")
set_wrapper(C.names, "names_wrapper")
[blurb
[$theme/note.gif]Even though Boost.Python accepts either a pointer or a
reference to the class in wrappers for member functions as the first parameter,
Pyste expects them to be a [*pointer]. Doing otherwise will prevent your
code to compile when you set a wrapper for a virtual member function.
]
[page:1 Exporting An Entire Header]
Pyste also supports a mechanism to export all declarations found in a header
file. Suppose again our file, [^hello.h]:
struct World
{
World(std::string msg): msg(msg) {}
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
enum choice { red, blue };
void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
You can just use the [^AllFromHeader] construct:
hello = AllFromHeader("hello.h")
this will export all the declarations found in [^hello.h], which is equivalent
to write:
Class("World", "hello.h")
Enum("choice", "hello.h")
Function("show", "hello.h")
Note that you can still use the functions [^rename], [^set_policy], [^exclude], etc. Just access
the members of the header object like this:
rename(hello.World.greet, "Greet")
exclude(hello.World.set, "Set")
[blurb
[$theme/note.gif] [*AllFromHeader is broken] in some cases. Until it is fixed,
use at you own risk.
]
[page:1 Smart Pointers]
Pyste for now has manual support for smart pointers. Suppose:
struct C
{
int value;
};
boost::shared_ptr<C> newC(int value)
{
boost::shared_ptr<C> c( new C() );
c->value = value;
return c;
}
void printC(boost::shared_ptr<C> c)
{
std::cout << c->value << std::endl;
}
To make [^newC] and [^printC] work correctly, you have to tell Pyste that a
convertor for [^boost::shared_ptr<C>] is needed.
C = Class('C', 'C.h')
use_shared_ptr(C)
Function('newC', 'C.h')
Function('printC', 'C.h')
For [^std::auto_ptr]'s, use the function [^use_auto_ptr].
This system is temporary, and in the future the converters will automatically be
exported if needed, without the need to tell Pyste about them explicitly.
[h2 Holders]
If only the converter for the smart pointers is not enough and you need to
specify the smart pointer as the holder for a class, use the functions
[^hold_with_shared_ptr] and [^hold_with_auto_ptr]:
C = Class('C', 'C.h')
hold_with_shared_ptr(C)
Function('newC', 'C.h')
Function('printC', 'C.h')
[page:1 Global Variables]
To export global variables, use the [^Var] construct:
Var("myglobal", "foo.h")
Beware of non-const global variables: changes in Python won't reflect in C++!
If you really must change them in Python, you will have to write some accessor
functions, and export those.
[page:1 Adding New Methods]
Suppose that you want to add a function to a class, turning it into a member
function:
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string msg;
};
std::string greet(World& w)
{
return w.msg;
}
Here, we want to make [^greet] work as a member function of the class [^World]. We do
that using the [^add_method] construct:
W = Class("World", "hello.h")
add_method(W, "greet")
Notice also that then you can rename it, set its policy, just like a regular
member function:
rename(W.greet, 'Greet')
Now from Python:
>>> import hello
>>> w = hello.World()
>>> w.set('Ni')
>>> w.greet()
'Ni'
>>> print 'Oh no! The knights who say Ni!'
Oh no! The knights who say Ni!
[page:1 Inserting Code]
You can insert arbitrary code in the generated cpps, just use the functions
[^declaration_code] and [^module_code]. This will insert the given string in the
respective sections. Example:
# file A.pyste
Class("A", "A.h")
declaration_code("/* declaration_code() comes here */\n")
module_code("/* module_code() comes here */\n")
Will generate:
// Includes ====================================================================
#include <boost/python.hpp>
// Using =======================================================================
using namespace boost::python;
// Declarations ================================================================
/* declaration_code() comes here */
// Module ======================================================================
BOOST_PYTHON_MODULE(A)
{
class_< A >("A", init< >())
.def(init< const A& >())
;
/* module_code() comes here */
}

View File

@@ -1,87 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Renaming and Excluding</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="the_interface_files.html">
<link rel="next" href="policies.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Renaming and Excluding</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="the_interface_files.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
You can easily rename functions, classes, member functions, attributes, etc. Just use the
function <tt>rename</tt>, like this:</p>
<code><pre>
<span class=identifier>World </span><span class=special>= </span><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>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>, </span><span class=string>&quot;IWorld&quot;</span><span class=special>)
</span><span class=identifier>show </span><span class=special>= </span><span class=identifier>Function</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>rename</span><span class=special>(</span><span class=identifier>show</span><span class=special>, </span><span class=string>&quot;Show&quot;</span><span class=special>)
</span></pre></code>
<p>
You can rename member functions and attributes using this syntax:</p>
<code><pre>
<span class=identifier>rename</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>rename</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><span class=identifier>choice </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>rename</span><span class=special>(</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>red</span><span class=special>, </span><span class=string>&quot;Red&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>blue</span><span class=special>, </span><span class=string>&quot;Blue&quot;</span><span class=special>)
</span></pre></code>
<p>
You can exclude functions, classes, member functions, attributes, etc, in the same way,
with the function <tt>exclude</tt>:</p>
<code><pre>
<span class=identifier>exclude</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=identifier>exclude</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>msg</span><span class=special>)
</span></pre></code>
<p>
To access the operators of a class, access the member <tt>operator</tt> like this
(supposing that <tt>C</tt> is a class being exported):</p>
<code><pre>
<span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'+'</span><span class=special>])
</span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'*'</span><span class=special>])
</span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'&lt;&lt;'</span><span class=special>])
</span></pre></code>
<p>
The string inside the brackets is the same as the name of the operator in C++.<br></p>
<a name="virtual_member_functions"></a><h2>Virtual Member Functions</h2><p>
Pyste automatically generates wrappers for virtual member functions, but you may
want to disable this behaviour (for performance reasons, for instance) if you do
not plan to override the functions in Python. To do this, use the function
<tt>final</tt>:</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>final</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>) </span>##<span class=identifier>C</span><span class=special>::</span><span class=identifier>foo </span><span class=identifier>is </span><span class=identifier>a </span><span class=keyword>virtual </span><span class=identifier>member </span><span class=identifier>function
</span></pre></code>
<p>
No virtual wrapper code will be generated for the virtual member function
C::foo that way.</p>
<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="the_interface_files.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="policies.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,200 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Running Pyste</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="introduction.html">
<link rel="next" href="the_interface_files.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Running Pyste</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="introduction.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="the_interface_files.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
To run Pyste, you will need:</p>
<ul><li>Python 2.2, available at <a href="http://www.python.org">
python's website</a>.</li><li>The great <a href="http://effbot.org">
elementtree</a> library, from Fredrik Lundh.</li><li>The excellent <a href="http://www.gccxml.org">
GCCXML</a>, from Brad King.</li></ul><p>
Installation for the tools is available in their respective webpages.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <a href="http://www.gccxml.org">
GCCXML</a> must be accessible in the PATH environment variable, so
that Pyste can call it. How to do this varies from platform to platform.
</td>
</tr>
</table>
<a name="ok__now_what_"></a><h2>Ok, now what?</h2><p>
Well, now let's fire it up:</p>
<code><pre>
&gt;python pyste.py
Pyste version 0.9.26
Usage:
pyste [options] interface-files
where options are:
--module=&lt;name&gt; The name of the module that will be generated;
defaults to the first interface filename, without
the extension.
-I &lt;path&gt; Add an include path
-D &lt;symbol&gt; Define symbol
--multiple Create various cpps, instead of only one
(useful during development)
--out=&lt;name&gt; Specify output filename (default: &lt;module&gt;.cpp)
in --multiple mode, this will be a directory
--no-using Do not declare &quot;using namespace boost&quot;;
use explicit declarations instead
--pyste-ns=&lt;name&gt; Set the namespace where new types will be declared;
default is the empty namespace
--debug Writes the xml for each file parsed in the current
directory
--cache-dir=&lt;dir&gt; Directory for cache files (speeds up future runs)
--only-create-cache Recreates all caches (doesn't generate code).
--generate-main Generates the _main.cpp file (in multiple mode)
--file-list A file with one pyste file per line. Use as a
substitute for passing the files in the command
line.
-h, --help Print this help and exit
-v, --version Print version information
</pre></code><p>
Options explained:</p>
<p>
The <tt>-I</tt> and <tt>-D</tt> are preprocessor flags, which are needed by <a href="http://www.gccxml.org">
GCCXML</a> to parse
the header files correctly and by Pyste to find the header files declared in the
interface files.</p>
<p>
<tt>--out</tt> names the output file (default: <tt>&lt;module&gt;.cpp</tt>), or in multiple mode,
names a output directory for the files (default: <tt>&lt;module&gt;</tt>).</p>
<p>
<tt>--no-using</tt> tells Pyste to don't declare &quot;<tt>using namespace boost;</tt>&quot; in the
generated cpp, using the namespace boost::python explicitly in all declarations.
Use only if you're having a name conflict in one of the files.</p>
<p>
Use <tt>--pyste-ns</tt> to change the namespace where new types are declared (for
instance, the virtual wrappers). Use only if you are having any problems. By
default, Pyste uses the empty namespace.</p>
<p>
<tt>--debug</tt> will write in the current directory a xml file as outputted by <a href="http://www.gccxml.org">
GCCXML</a>
for each header parsed. Useful for bug reports.</p>
<p>
<tt>--file-list</tt> names a file where each line points to a Pyste file. Use this instead
to pass the pyste files if you have a lot of them and your shell has some command line
size limit.</p>
<p>
The other options are explained below, in <a href="#multiple_mode">
<b>Multiple Mode</b></a> and
<a href="#cache">
<b>Cache</b></a>.</p>
<p>
<tt>-h, --help, -v, --version</tt> are self-explaining, I believe. ;)</p>
<p>
So, the usage is simple enough:</p>
<code><pre>&gt;python pyste.py --module=mymodule file.pyste file2.pyste ...</pre></code><p>
will generate a file <tt>mymodule.cpp</tt> in the same dir where the command was
executed. Now you can compile the file using the same instructions of the
<a href="../../doc/tutorial/doc/html/python/hello.html">
tutorial</a>. </p>
<a name="wait____how_do_i_set_those_i_and_d_flags_"></a><h2>Wait... how do I set those I and D flags?</h2><p>
Don't worry: normally <a href="http://www.gccxml.org">
GCCXML</a> is already configured correctly for your plataform,
so the search path to the standard libraries and the standard defines should
already be set. You only have to set the paths to other libraries that your code
needs, like Boost, for example.</p>
<p>
Plus, Pyste automatically uses the contents of the environment variable
<tt>INCLUDE</tt> if it exists. Visual C++ users should run the <tt>Vcvars32.bat</tt> file,
which for Visual C++ 6 is normally located at:</p>
<code><pre>
<span class=identifier>C</span><span class=special>:\</span><span class=identifier>Program </span><span class=identifier>Files</span><span class=special>\</span><span class=identifier>Microsoft </span><span class=identifier>Visual </span><span class=identifier>Studio</span><span class=special>\</span><span class=identifier>VC98</span><span class=special>\</span><span class=identifier>bin</span><span class=special>\</span><span class=identifier>Vcvars32</span><span class=special>.</span><span class=identifier>bat
</span></pre></code>
<p>
with that, you should have little trouble setting up the flags.</p>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img><b>A note about Psyco</b><br><br>
Although you don't have to install <a href="http://psyco.sourceforge.net/">
Psyco</a> to
use Pyste, if you do, Pyste will make use of it to speed up the wrapper
generation. Speed ups of 30% can be achieved, so it's highly recommended.
</td>
</tr>
</table>
<a name="multiple_mode"></a><h2>Multiple Mode</h2><p>
The multiple mode is useful in large projects, where the presence of multiple
classes in a single file makes the compilation unpractical (excessive memory
usage, mostly). </p>
<p>
The solution is make Pyste generate multiple files, more specifically one cpp
file for each Pyste file. This files will contain a function named after the
file, for instance Export_MyPysteFile, which will contain all the code to export
the classes, enums, etc. You can pass as much files as you want this way:</p>
<code><pre>&gt;python pyste.py --module=mymodule file1.pyste file2.pyste</pre></code><p>
This will create the files <tt>mymodule/file1.cpp</tt> and <tt>mymodule/file2.cpp</tt>. You
can then later do:</p>
<code><pre>&gt;python pyste.py --module=mymodule file3.pyste</pre></code><p>
and <tt>mymodule/file3.cpp</tt> will be generated.</p>
<p>
But compiling and linking this files won't be sufficient to generate your
extension. You have to also generate a file named <tt>main.cpp</tt>; call pyste with
<b>all</b> the Pyste files of your extension, and use the <tt>--generate-main</tt> option:</p>
<code><pre>&gt;python pyste.py --module=mymodule --generate-main file1.pyste file2.pyste file3.pyste</pre></code><p>
Now compile and link all this files together and your extension is ready for
use.</p>
<a name="cache"></a><h2>Cache</h2><p>
Pyste now supports a form of cache, which is a way to speed up the code
generation. Most of the time that Pyste takes to generate the code comes from
having to execute <a href="http://www.gccxml.org">
GCCXML</a> (since being a front-end to GCC, it has to compile the
header files) and reading back the XML generated. </p>
<p>
When you use the <tt>--cache-dir=&lt;dir&gt;</tt> option, Pyste will dump in the specified
directory the generated XMLs to a file named after the Pyste file, with the
extension <tt>.pystec</tt>. The next time you run with this option, Pyste will use
the cache, instead of calling <a href="http://www.gccxml.org">
GCCXML</a> again:</p>
<code><pre>&gt;python pyste.py --module=mymodule --cache-dir=cache file1.pyste</pre></code><p>
Will generate <tt>file1.cpp</tt> and <tt>cache/file1.pystec</tt>. Next time you execute
this command, the cache file will be used. Note that Pyste doesn't do any check
to ensure that the cache is up to date, but you can configure your build system to do that for you.</p>
<p>
When you run Pyste with <tt>--only-create-cache</tt>, all the cache files will be
created again, but no code will be generated.</p>
<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="introduction.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="the_interface_files.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,84 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Smart Pointers</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="exporting_an_entire_header.html">
<link rel="next" href="global_variables.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Smart Pointers</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="exporting_an_entire_header.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="global_variables.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Pyste for now has manual support for smart pointers. Suppose:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>C
</span><span class=special>{
</span><span class=keyword>int </span><span class=identifier>value</span><span class=special>;
};
</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>newC</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>value</span><span class=special>)
{
</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>c</span><span class=special>( </span><span class=keyword>new </span><span class=identifier>C</span><span class=special>() );
</span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>value </span><span class=special>= </span><span class=identifier>value</span><span class=special>;
</span><span class=keyword>return </span><span class=identifier>c</span><span class=special>;
}
</span><span class=keyword>void </span><span class=identifier>printC</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </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=identifier>c</span><span class=special>-&gt;</span><span class=identifier>value </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>
To make <tt>newC</tt> and <tt>printC</tt> work correctly, you have to tell Pyste that a
convertor for <tt>boost::shared_ptr&lt;C&gt;</tt> is needed.</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>use_shared_ptr</span><span class=special>(</span><span class=identifier>C</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'newC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'printC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span></pre></code>
<p>
For <tt>std::auto_ptr</tt>'s, use the function <tt>use_auto_ptr</tt>.</p>
<p>
This system is temporary, and in the future the converters will automatically be
exported if needed, without the need to tell Pyste about them explicitly.</p>
<a name="holders"></a><h2>Holders</h2><p>
If only the converter for the smart pointers is not enough and you need to
specify the smart pointer as the holder for a class, use the functions
<tt>hold_with_shared_ptr</tt> and <tt>hold_with_auto_ptr</tt>:</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>hold_with_shared_ptr</span><span class=special>(</span><span class=identifier>C</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'newC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
</span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'printC'</span><span class=special>, </span><span class=literal>'C.h'</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="exporting_an_entire_header.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="global_variables.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,102 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Templates</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="policies.html">
<link rel="next" href="wrappers.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Templates</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="policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="wrappers.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Template classes can easily be exported too, but you can't export the template
itself... you have to export instantiations of it! So, if you want to export a
<tt>std::vector</tt>, you will have to export vectors of int, doubles, etc.</p>
<p>
Suppose we have this code:</p>
<code><pre>
<span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>class </span><span class=identifier>T</span><span class=special>&gt;
</span><span class=keyword>struct </span><span class=identifier>Point
</span><span class=special>{
</span><span class=identifier>T </span><span class=identifier>x</span><span class=special>;
</span><span class=identifier>T </span><span class=identifier>y</span><span class=special>;
};
</span></pre></code>
<p>
And we want to export <tt>Point</tt>s of int and double:</p>
<code><pre>
<span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>)
</span></pre></code>
<p>
Pyste will assign default names for each instantiation. In this example, those
would be &quot;<tt>Point_int</tt>&quot; and &quot;<tt>Point_double</tt>&quot;, but most of the time users will want to
rename the instantiations:</p>
<code><pre>
<span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>) // </span><span class=identifier>renames </span><span class=identifier>the </span><span class=identifier>instantiation
</span><span class=identifier>double_inst </span><span class=special>= </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>) // </span><span class=identifier>another </span><span class=identifier>way </span><span class=identifier>to </span><span class=keyword>do </span><span class=identifier>the </span><span class=identifier>same
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>double_inst</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>)
</span></pre></code>
<p>
Note that you can rename, exclude, set policies, etc, in the <tt>Template</tt> object
like you would do with a <tt>Function</tt> or a <tt>Class</tt>. This changes affect all
<b>future</b> instantiations:</p>
<code><pre>
<span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;float&quot;</span><span class=special>, </span><span class=string>&quot;FPoint&quot;</span><span class=special>) // </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>x </span><span class=keyword>and </span><span class=identifier>y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>members
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>Point</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=string>&quot;X&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>Point</span><span class=special>.</span><span class=identifier>y</span><span class=special>, </span><span class=string>&quot;Y&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>) // </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>X </span><span class=keyword>and </span><span class=identifier>Y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>members
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>) // </span><span class=identifier>also </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>X </span><span class=keyword>and </span><span class=identifier>Y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>member
</span></pre></code>
<p>
If you want to change a option of a particular instantiation, you can do so:</p>
<code><pre>
<span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
</span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>)
</span><span class=identifier>d_inst </span><span class=special>= </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>)
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>d_inst</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=string>&quot;X&quot;</span><span class=special>) // </span><span class=identifier>only </span><span class=identifier>DPoint </span><span class=identifier>is </span><span class=identifier>affect </span><span class=identifier>by </span><span class=keyword>this </span><span class=identifier>renames</span><span class=special>,
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>d_inst</span><span class=special>.</span><span class=identifier>y</span><span class=special>, </span><span class=string>&quot;Y&quot;</span><span class=special>) // </span><span class=identifier>IPoint </span><span class=identifier>stays </span><span class=identifier>intact
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img> <b>What if my template accepts more than one type?</b>
<br><br>
When you want to instantiate a template with more than one type, you can pass
either a string with the types separated by whitespace, or a list of strings
(&quot;int double&quot; or [&quot;int&quot;, &quot;double&quot;] would both work).
</td>
</tr>
</table>
<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="policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="wrappers.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,102 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>The Interface Files</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="running_pyste.html">
<link rel="next" href="renaming_and_excluding.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>The Interface Files</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="running_pyste.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="renaming_and_excluding.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
The interface files are the heart of Pyste. The user creates one or more
interface files declaring the classes and functions he wants to export, and then
invokes Pyste passing the interface files to it. Pyste then generates a single
cpp file with <a href="../../index.html">
Boost.Python</a> code, with all the classes and functions exported.</p>
<p>
Besides declaring the classes and functions, the user has a number of other
options, like renaming e excluding classes and member functionis. Those are
explained later on.</p>
<a name="basics"></a><h2>Basics</h2><p>
Suppose we have a class and some functions that we want to expose to Python
declared in the header <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>namespace </span><span class=identifier>test </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>
We create a file named <tt>hello.pyste</tt> and create instances of the classes
<tt>Function</tt>, <tt>Class</tt> and <tt>Enum</tt>:</p>
<code><pre>
<span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;test::show&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
</span><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></pre></code>
<p>
That will expose the class, the free function and the enum found in <tt>hello.h</tt>. </p>
<a name="inheritance"></a><h2>Inheritance</h2><p>
Pyste automatically generates the correct code (specifying <tt>bases&lt;&gt;</tt> in the
<tt>class_</tt> declaration) <b>if</b> the Class() function that exports the base classes
and their children are in the same Pyste file. If that's not the case, you have
to indicate that there's a relationship between the Pyste files using the
<tt>Import</tt> function specifying the other Pyste file.</p>
<p>
Suppose we have two classes, <tt>A</tt> and <tt>B</tt>, and A is a base class for B. We
create two Pyste files:</p>
<p>
<tt>A.pyste</tt>:</p>
<code><pre>
<span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;A&quot;</span><span class=special>, </span><span class=string>&quot;A.h&quot;</span><span class=special>)
</span></pre></code>
<p>
<tt>B.pyste</tt>:</p>
<code><pre>
<span class=identifier>Import</span><span class=special>(</span><span class=string>&quot;A.pyste&quot;</span><span class=special>)
</span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;B&quot;</span><span class=special>, </span><span class=string>&quot;B.h&quot;</span><span class=special>)
</span></pre></code>
<p>
Note that we specify that <tt>B</tt> needs to know about <tt>A</tt> to be properly exported.</p>
<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="running_pyste.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="renaming_and_excluding.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 B

View File

@@ -1,178 +0,0 @@
/*=============================================================================
Copyright (c) 2003 Bruno da Silva de Oliveira
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
body
{
background-image: url(bkd.gif);
background-color: #FFFFFF;
margin: 1em 2em 1em 2em;
}
h1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; text-align: left; }
h2 { font: 140% sans-serif; font-weight: bold; text-align: left; }
h3 { font: 120% sans-serif; font-weight: bold; text-align: left; }
h4 { font: bold 100% sans-serif; font-weight: bold; text-align: left; }
h5 { font: italic 100% sans-serif; font-weight: bold; text-align: left; }
h6 { font: small-caps 100% sans-serif; font-weight: bold; text-align: left; }
pre
{
border-top: gray 1pt solid;
border-right: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
padding-top: 2pt;
padding-right: 2pt;
padding-left: 2pt;
padding-bottom: 2pt;
display: block;
font-family: "courier new", courier, mono;
background-color: #eeeeee; font-size: small
}
code
{
font-family: "Courier New", Courier, mono;
font-size: small
}
tt
{
display: inline;
font-family: "Courier New", Courier, mono;
color: #000099;
font-size: small
}
p
{
text-align: justify;
font-family: Georgia, "Times New Roman", Times, serif
}
ul
{
list-style-image: url(bullet.gif);
font-family: Georgia, "Times New Roman", Times, serif
}
ol
{
font-family: Georgia, "Times New Roman", Times, serif
}
a
{
font-weight: bold;
color: #003366;
text-decoration: none;
}
a:hover { color: #8080FF; }
.literal { color: #666666; font-style: italic}
.keyword { color: #000099}
.identifier {}
.comment { font-style: italic; color: #990000}
.special { color: #800040}
.preprocessor { color: #FF0000}
.string { font-style: italic; color: #666666}
.copyright { color: #666666; font-size: small}
.white_bkd { background-color: #FFFFFF}
.dk_grey_bkd { background-color: #999999}
.quotes { color: #666666; font-style: italic; font-weight: bold}
.note_box
{
display: block;
border-top: gray 1pt solid;
border-right: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
padding-right: 12pt;
padding-left: 12pt;
padding-bottom: 12pt;
padding-top: 12pt;
font-family: Arial, Helvetica, sans-serif;
background-color: #E2E9EF;
font-size: small; text-align: justify
}
.table_title
{
background-color: #648CCA;
font-family: Verdana, Arial, Helvetica, sans-serif; color: #FFFFFF;
font-weight: bold
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
}
.table_cells
{
background-color: #E2E9EF;
font-family: Geneva, Arial, Helvetica, san-serif;
font-size: small
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
}
.toc
{
DISPLAY: block;
background-color: #E2E9EF
font-family: Arial, Helvetica, sans-serif;
border-top: gray 1pt solid;
border-left: gray 1pt solid;
border-bottom: gray 1pt solid;
border-right: gray 1pt solid;
padding-top: 24pt;
padding-right: 24pt;
padding-left: 24pt;
padding-bottom: 24pt;
}
.toc_title
{
background-color: #648CCA;
padding-top: 4px;
padding-right: 4px;
padding-bottom: 4px;
padding-left: 4px;
font-family: Geneva, Arial, Helvetica, san-serif;
color: #FFFFFF;
font-weight: bold
}
.toc_cells
{
background-color: #E2E9EF;
padding-top: 4px;
padding-right: 4px;
padding-bottom: 4px;
padding-left: 4px;
font-family: Geneva, Arial, Helvetica, san-serif;
font-size: small
}
div.logo
{
float: right;
}
.toc_cells_L0 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L1 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 44px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L2 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 88px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L3 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 122px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
.toc_cells_L4 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 166px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

View File

@@ -1,124 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Wrappers</title>
<link rel="stylesheet" href="theme/style.css" type="text/css">
<link rel="prev" href="templates.html">
<link rel="next" href="exporting_an_entire_header.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Wrappers</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="templates.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exporting_an_entire_header.html"><img src="theme/r_arr.gif" border="0"></a></td>
</tr>
</table>
<p>
Suppose you have this function:</p>
<code><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>names</span><span class=special>();
</span></pre></code>
<p>
But you don't want to <a href="../../doc/v2/faq.html#question2">
to export std::vector&lt;std::string&gt;</a>,
you want this function to return a python list of strings. <a href="../../index.html">
Boost.Python</a> has
excellent support for things like that:</p>
<code><pre>
<span class=identifier>list </span><span class=identifier>names_wrapper</span><span class=special>()
{
</span><span class=identifier>list </span><span class=identifier>result</span><span class=special>;
// </span><span class=identifier>call </span><span class=identifier>original </span><span class=identifier>function
</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>v </span><span class=special>= </span><span class=identifier>names</span><span class=special>();
// </span><span class=identifier>put </span><span class=identifier>all </span><span class=identifier>the </span><span class=identifier>strings </span><span class=identifier>inside </span><span class=identifier>the </span><span class=identifier>python </span><span class=identifier>list
</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>string</span><span class=special>&gt;::</span><span class=identifier>iterator </span><span class=identifier>it</span><span class=special>;
</span><span class=keyword>for </span><span class=special>(</span><span class=identifier>it </span><span class=special>= </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(); </span><span class=identifier>it </span><span class=special>!= </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>end</span><span class=special>(); ++</span><span class=identifier>it</span><span class=special>){
</span><span class=identifier>result</span><span class=special>.</span><span class=identifier>append</span><span class=special>(*</span><span class=identifier>it</span><span class=special>);
}
</span><span class=keyword>return </span><span class=identifier>result</span><span class=special>;
}
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>test</span><span class=special>)
{
</span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, &amp;</span><span class=identifier>names_wrapper</span><span class=special>);
}
</span></pre></code>
<p>
Nice heh? Pyste supports this mechanism too. You declare the <tt>names_wrapper</tt>
function in a header named &quot;<tt>test_wrappers.h</tt>&quot; and in the interface file:</p>
<code><pre>
<span class=identifier>Include</span><span class=special>(</span><span class=string>&quot;test_wrappers.h&quot;</span><span class=special>)
</span><span class=identifier>names </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
</span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>names</span><span class=special>, </span><span class=string>&quot;names_wrapper&quot;</span><span class=special>)
</span></pre></code>
<p>
You can optionally declare the function in the interface file itself:</p>
<code><pre>
<span class=identifier>names_wrapper </span><span class=special>= </span><span class=identifier>Wrapper</span><span class=special>(</span><span class=string>&quot;names_wrapper&quot;</span><span class=special>,
</span><span class=string>&quot;&quot;</span><span class=string>&quot;
list names_wrapper()
{
// code to call name() and convert the vector to a list...
}
&quot;</span><span class=string>&quot;&quot;</span><span class=special>)
</span><span class=identifier>names </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
</span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>names</span><span class=special>, </span><span class=identifier>names_wrapper</span><span class=special>)
</span></pre></code>
<p>
The same mechanism can be used with member functions too. Just remember that
the first parameter of wrappers for member functions is a pointer to the
class, as in:</p>
<code><pre>
<span class=keyword>struct </span><span class=identifier>C
</span><span class=special>{
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>names</span><span class=special>();
}
</span><span class=identifier>list </span><span class=identifier>names_wrapper</span><span class=special>(</span><span class=identifier>C</span><span class=special>* </span><span class=identifier>c</span><span class=special>)
{
// </span><span class=identifier>same </span><span class=identifier>as </span><span class=identifier>before</span><span class=special>, </span><span class=identifier>calling </span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>names</span><span class=special>() </span><span class=keyword>and </span><span class=identifier>converting </span><span class=identifier>result </span><span class=identifier>to </span><span class=identifier>a </span><span class=identifier>list
</span><span class=special>}
</span></pre></code>
<p>
And then in the interface file:</p>
<code><pre>
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;C&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
</span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>names</span><span class=special>, </span><span class=string>&quot;names_wrapper&quot;</span><span class=special>)
</span></pre></code>
<table width="80%" border="0" align="center">
<tr>
<td class="note_box">
<img src="theme/note.gif"></img>Even though <a href="../../index.html">
Boost.Python</a> accepts either a pointer or a
reference to the class in wrappers for member functions as the first parameter,
Pyste expects them to be a <b>pointer</b>. Doing otherwise will prevent your
code to compile when you set a wrapper for a virtual member function.
</td>
</tr>
</table>
<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="templates.html"><img src="theme/l_arr.gif" border="0"></a></td>
<td width="20"><a href="exporting_an_entire_header.html"><img src="theme/r_arr.gif" border="0"></a></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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,90 +0,0 @@
<html>
<head>
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
<title>Pyste Documentation</title>
<link rel="stylesheet" href="doc/theme/style.css" type="text/css">
<link rel="next" href="doc/introduction.html">
</head>
<body>
<table width="100%" height="48" border="0" cellspacing="2">
<tr>
<td><img src="../../../boost.png">
</td>
<td width="85%">
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Pyste Documentation</b></font>
</td>
</tr>
</table>
<br>
<table width="80%" border="0" align="center">
<tr>
<td class="toc_title">Table of contents</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/introduction.html">Introduction</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/running_pyste.html">Running Pyste</a>
</td>
</tr>
<tr>
<td class="toc_cells_L0">
<a href="doc/the_interface_files.html">The Interface Files</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/renaming_and_excluding.html">Renaming and Excluding</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/policies.html">Policies</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/templates.html">Templates</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/wrappers.html">Wrappers</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/exporting_an_entire_header.html">Exporting An Entire Header</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/smart_pointers.html">Smart Pointers</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/global_variables.html">Global Variables</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/adding_new_methods.html">Adding New Methods</a>
</td>
</tr>
<tr>
<td class="toc_cells_L1">
<a href="doc/inserting_code.html">Inserting Code</a>
</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">Distributed under
the Boost Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
</body>
</html>

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env python
# Copyright Bruno da Silva de Oliveira 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
from Pyste import pyste
pyste.main()

View File

@@ -1,20 +0,0 @@
# Copyright Prabhu Ramachandran 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
from distutils.core import setup
import sys
setup (name = "Pyste",
version = "0.9.10",
description = "Pyste - Python Semi-Automatic Exporter",
maintainer = "Bruno da Silva de Oliveira",
maintainer_email = "nicodemus@globalite.com.br",
licence = "Boost License",
long_description = "Pyste is a Boost.Python code generator",
url = "http://www.boost.org/libs/python/pyste/index.html",
platforms = ['Any'],
packages = ['Pyste'],
scripts = ['pyste.py'],
package_dir = {'Pyste': '../src/Pyste'},
)

View File

@@ -1,918 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import exporters
from Exporter import Exporter
from declarations import *
from settings import *
from policies import *
from SingleCodeUnit import SingleCodeUnit
from EnumExporter import EnumExporter
from utils import makeid, enumerate
import copy
import exporterutils
import re
#==============================================================================
# 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['declaration-outside'] = []
self.sections['include'] = []
# a list of Constructor instances
self.constructors = []
# a list of code units, generated by nested declarations
self.nested_codeunits = []
def ScopeName(self):
return makeid(self.class_.FullName()) + '_scope'
def Name(self):
return self.info.name
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
if self.declarations:
decl = self.GetDeclaration(self.info.name)
if isinstance(decl, Typedef):
self.class_ = self.GetDeclaration(decl.type.name)
if not self.info.rename:
self.info.rename = decl.name
else:
self.class_ = decl
self.class_ = copy.deepcopy(self.class_)
else:
self.class_ = None
def ClassBases(self):
all_bases = []
for level in self.class_.hierarchy:
for base in level:
all_bases.append(base)
return [self.GetDeclaration(x.name) for x in all_bases]
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.
'''
num_bases = len(self.ClassBases())
return num_bases, self.class_.FullName()
def Export(self, codeunit, exported_names):
self.InheritMethods(exported_names)
self.MakeNonVirtual()
if not self.info.exclude:
self.ExportBasics()
self.ExportBases(exported_names)
self.ExportConstructors()
self.ExportVariables()
self.ExportVirtualMethods(codeunit)
self.ExportMethods()
self.ExportOperators()
self.ExportNestedClasses(exported_names)
self.ExportNestedEnums(exported_names)
self.ExportSmartPointer()
self.ExportOpaquePointerPolicies()
self.ExportAddedCode()
self.Write(codeunit)
exported_names[self.Name()] = 1
def InheritMethods(self, exported_names):
'''Go up in the class hierarchy looking for classes that were not
exported yet, and then add their public members to this classes
members, as if they were members of this class. This allows the user to
just export one type and automatically get all the members from the
base classes.
'''
valid_members = (Method, ClassVariable, NestedClass, ClassEnumeration)
fullnames = [x.FullName() for x in self.class_]
pointers = [x.PointerDeclaration(True) for x in self.class_ if isinstance(x, Method)]
fullnames = dict([(x, None) for x in fullnames])
pointers = dict([(x, None) for x in pointers])
for level in self.class_.hierarchy:
level_exported = False
for base in level:
base = self.GetDeclaration(base.name)
if base.FullName() not in exported_names:
for member in base:
if type(member) in valid_members:
member_copy = copy.deepcopy(member)
member_copy.class_ = self.class_.FullName()
if isinstance(member_copy, Method):
pointer = member_copy.PointerDeclaration(True)
if pointer not in pointers:
self.class_.AddMember(member)
pointers[pointer] = None
elif member_copy.FullName() not in fullnames:
self.class_.AddMember(member)
else:
level_exported = True
if level_exported:
break
def IsValid(member):
return isinstance(member, valid_members) and member.visibility == Scope.public
self.public_members = [x for x in self.class_ if IsValid(x)]
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')
declarations_outside = '\n'.join(self.sections['declaration-outside'])
if declarations_outside:
codeunit.Write('declaration-outside', declarations_outside + '\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.'''
class_name = self.class_.FullName()
self.Add('template', class_name)
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'
hierarchy = self.class_.hierarchy
exported = []
for level in hierarchy:
for base in level:
if base.visibility == Scope.public and base.name in exported_names:
exported.append(base.name)
if exported:
break
if exported:
code = namespaces.python + 'bases< %s > ' % (', '.join(exported))
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)]
# don't export copy constructors if the class is abstract
# we could remove all constructors, but this will have the effect of
# inserting no_init in the declaration, which would not allow
# even subclasses to be instantiated.
self.constructors = constructors[:]
if self.class_.abstract:
for cons in constructors:
if cons.IsCopy():
constructors.remove(cons)
break
if not constructors:
# declare no_init
self.Add('constructor', py_ns + 'no_init')
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.type.const:
def_ = '.def_readonly'
else:
def_ = '.def_readwrite'
code = '%s("%s", &%s)' % (def_, name, fullname)
self.Add('inside', code)
def OverloadName(self, method):
'Returns the name of the overloads struct for the given method'
name = makeid(method.FullName())
overloads = '_overloads_%i_%i' % (method.minArgs, method.maxArgs)
return name + overloads
def GetAddedMethods(self):
added_methods = self.info.__added__
result = []
if added_methods:
for name, rename in added_methods:
decl = self.GetDeclaration(name)
self.info[name].rename = rename
result.append(decl)
return result
def ExportMethods(self):
'''Export all the non-virtual methods of this class, plus any function
that is to be exported as a method'''
declared = {}
def DeclareOverloads(m):
'Declares the macro for the generation of the overloads'
if (isinstance(m, Method) and m.static) or type(m) == Function:
func = m.FullName()
macro = 'BOOST_PYTHON_FUNCTION_OVERLOADS'
else:
func = m.name
macro = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS'
code = '%s(%s, %s, %i, %i)\n' % (macro, self.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[m.name].wrapper
if wrapper:
return '&' + wrapper.FullName()
else:
return m.PointerDeclaration()
def IsExportable(m):
'Returns true if the given method is exportable by this routine'
ignore = (Constructor, ClassOperator, Destructor)
return isinstance(m, Function) and not isinstance(m, ignore) and not m.virtual
methods = [x for x in self.public_members if IsExportable(x)]
methods.extend(self.GetAddedMethods())
staticmethods = {}
for method in methods:
method_info = self.info[method.name]
# skip this method if it was excluded by the user
if method_info.exclude:
continue
# rename the method if the user requested
name = method_info.rename or method.name
# warn the user if this method needs a policy and doesn't have one
method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
# check for policies
policy = method_info.policy or ''
if policy:
policy = ', %s%s()' % (namespaces.python, policy.Code())
# check for overloads
overload = ''
if method.minArgs != method.maxArgs and not method_info.wrapper:
# add the overloads for this method
DeclareOverloads(method)
overload_name = self.OverloadName(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 isinstance(method, Method) and method.static:
staticmethods[name] = 1
# add wrapper code if this method has one
wrapper = method_info.wrapper
if wrapper and wrapper.code:
self.Add('declaration', wrapper.code)
# export staticmethod statements
for name in staticmethods:
code = '.staticmethod("%s")' % name
self.Add('inside', code)
def MakeNonVirtual(self):
'''Make all methods that the user indicated to no_override no more virtual, delegating their
export to the ExportMethods routine'''
for member in self.class_:
if type(member) == Method and member.virtual:
member.virtual = not self.info[member.name].no_override
def ExportVirtualMethods(self, codeunit):
# check if this class has any virtual methods
has_virtual_methods = False
for member in self.class_:
if type(member) == Method and member.virtual:
has_virtual_methods = True
break
holder = self.info.holder
if has_virtual_methods:
generator = _VirtualWrapperGenerator(self.class_, self.ClassBases(), self.info, codeunit)
if holder:
self.Add('template', holder(generator.FullName()))
else:
self.Add('template', generator.FullName())
for definition in generator.GenerateDefinitions():
self.Add('inside', definition)
self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT))
else:
if holder:
self.Add('template', holder(self.class_.FullName()))
# 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 name
BOOST_RENAME_OPERATORS = {
'()' : '__call__',
}
# converters which have a special name in python
# it's a map of a regular expression of the converter's result to the
# appropriate python name
SPECIAL_CONVERTERS = {
re.compile(r'(const)?\s*double$') : '__float__',
re.compile(r'(const)?\s*float$') : '__float__',
re.compile(r'(const)?\s*int$') : '__int__',
re.compile(r'(const)?\s*long$') : '__long__',
re.compile(r'(const)?\s*char\s*\*?$') : '__str__',
re.compile(r'(const)?.*::basic_string<.*>\s*(\*|\&)?$') : '__str__',
}
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-outside', wrapper.code)
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.FullName()
result_name = converter.result.name
for regex, method_name in self.SPECIAL_CONVERTERS.items():
if regex.match(result_fullname):
return method_name
else:
# extract the last name from the full name
result_name = makeid(result_name)
return 'to_' + result_name
for converter in converters:
info = self.info['operator'][converter.result.FullName()]
# 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)
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 = self.__class__(nested_info)
exporter.SetDeclarations(self.declarations)
codeunit = SingleCodeUnit(None, None)
exporter.Export(codeunit, exported_names)
self.nested_codeunits.append(codeunit)
def ExportNestedEnums(self, exported_names):
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)
codeunit = SingleCodeUnit(None, None)
exporter.Export(codeunit, exported_names)
self.nested_codeunits.append(codeunit)
def ExportSmartPointer(self):
smart_ptr = self.info.smart_ptr
if smart_ptr:
class_name = self.class_.FullName()
smart_ptr = smart_ptr % class_name
self.Add('scope', '%sregister_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
def ExportOpaquePointerPolicies(self):
# check all methods for 'return_opaque_pointer' policies
methods = [x for x in self.public_members if isinstance(x, Method)]
for method in methods:
return_opaque_policy = return_value_policy(return_opaque_pointer)
if self.info[method.name].policy == return_opaque_policy:
macro = exporterutils.EspecializeTypeID(method.result.name)
if macro:
self.Add('declaration-outside', macro)
def ExportAddedCode(self):
if self.info.__code__:
for code in self.info.__code__:
self.Add('inside', code)
#==============================================================================
# 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_, bases, info, codeunit):
self.class_ = copy.deepcopy(class_)
self.bases = bases[:]
self.info = info
self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
self.virtual_methods = None
self._method_count = {}
self.codeunit = codeunit
self.GenerateVirtualMethods()
SELF = 'py_self'
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%s {\n' % (result, method.name, params, constantness, method.Exceptions())
param_names_str = ', '.join(param_names)
if param_names_str:
param_names_str = ', ' + param_names_str
self_str = self.SELF
decl += indent*2 + '%(return_str)s%(python)scall_method< %(result)s >' \
'(%(self_str)s, "%(rename)s"%(param_names_str)s);\n' % locals()
decl += indent + '}\n'
# default implementations (with overloading)
def DefaultImpl(method, param_names):
'Return the body of a default implementation wrapper'
indent2 = indent * 2
wrapper = self.info[method.name].wrapper
if not wrapper:
# return the default implementation of the class
return indent2 + '%s%s(%s);\n' % \
(return_str, method.FullName(), ', '.join(param_names))
else:
if wrapper.code:
self.codeunit.Write('declaration-outside', wrapper.code)
# return a call for the wrapper
params = ', '.join(['this'] + param_names)
return indent2 + '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
if not method.abstract and method.visibility != Scope.private:
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 += DefaultImpl(method, 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
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 = method.is_unique
constantness = ''
if method.const:
constantness = ' const'
# create a list of default-impl pointers
minArgs = method.minArgs
maxArgs = method.maxArgs
if method.abstract:
default_pointers = []
elif 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
pointer = method.PointerDeclaration()
if method.abstract:
pointer = namespaces.python + ('pure_virtual(%s)' % pointer)
# warn the user if this method needs a policy and doesn't have one
method_info = self.info[method.name]
method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
# Add policy to overloaded methods also
policy = method_info.policy or ''
if policy:
policy = ', %s%s()' % (namespaces.python, policy.Code())
# generate the defs
definitions = []
# basic def
if default_pointers:
definitions.append('.def("%s", %s, %s%s)' % (rename, pointer, default_pointers[-1], policy))
for default_pointer in default_pointers[:-1]:
definitions.append('.def("%s", %s%s)' % (rename, default_pointer, policy))
else:
definitions.append('.def("%s", %s%s)' % (rename, pointer, policy))
return definitions
def FullName(self):
return namespaces.pyste + self.wrapper_name
def GenerateVirtualMethods(self):
'''To correctly export all virtual methods, we must also make wrappers
for the virtual methods of the bases of this class, as if the methods
were from this class itself.
This method creates the instance variable self.virtual_methods.
'''
def IsVirtual(m):
if type(m) is Method:
pure_virtual = m.abstract and m.virtual
virtual = m.virtual and m.visibility != Scope.private
return virtual or pure_virtual
else:
return False
# extract the virtual methods, avoiding duplications. The duplication
# must take in account the full signature without the class name, so
# that inherited members are correctly excluded if the subclass overrides
# them.
def MethodSig(method):
if method.const:
const = ' const'
else:
const = ''
if method.result:
result = method.result.FullName()
else:
result = ''
params = ', '.join([x.FullName() for x in method.parameters])
return '%s %s(%s)%s%s' % (
result, method.name, params, const, method.Exceptions())
already_added = {}
self.virtual_methods = []
for member in self.class_:
if IsVirtual(member):
already_added[MethodSig(member)] = None
self.virtual_methods.append(member)
for base in self.bases:
base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
for base_method in base_methods:
self.class_.AddMember(base_method)
all_methods = [x for x in self.class_ if IsVirtual(x)]
for member in all_methods:
sig = MethodSig(member)
if IsVirtual(member) and not sig in already_added:
self.virtual_methods.append(member)
already_added[sig] = 0
def Constructors(self):
return self.class_.Constructors(publics_only=True)
def GenerateDefinitions(self):
defs = []
for method in self.virtual_methods:
exclude = self.info[method.name].exclude
# generate definitions only for public methods and non-abstract methods
if method.visibility == Scope.public and not 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(): # only public 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* %s_%s):\n' % \
(self.wrapper_name, self.SELF, params)
cons_code += indent*2 + '%s(%s), %s(%s_) {}\n\n' % \
(class_name, ', '.join(param_names), self.SELF, self.SELF)
code += cons_code
# generate the body
body = []
for method in self.virtual_methods:
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* %s;\n' % self.SELF
code += '};\n'
return code

View File

@@ -1,26 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from Exporter import Exporter
#==============================================================================
# CodeExporter
#==============================================================================
class CodeExporter(Exporter):
def __init__(self, info):
Exporter.__init__(self, info)
def Name(self):
return self.info.code
def Export(self, codeunit, exported_names):
codeunit.Write(self.info.section, self.info.code)
def WriteInclude(self, codeunit):
pass

View File

@@ -1,247 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from GCCXMLParser import ParseDeclarations
import tempfile
import shutil
import os
import sys
import os.path
import settings
import shutil
import shelve
from cPickle import dump, load
#==============================================================================
# exceptions
#==============================================================================
class CppParserError(Exception): pass
#==============================================================================
# CppParser
#==============================================================================
class CppParser:
'Parses a header file and returns a list of declarations'
def __init__(self, includes=None, defines=None, cache_dir=None, version=None, gccxml_path = 'gccxml'):
'includes and defines ar the directives given to gcc'
if includes is None:
includes = []
if defines is None:
defines = []
self.includes = includes
self.gccxml_path = gccxml_path
self.defines = defines
self.version = version
#if cache_dir is None:
# cache_dir = tempfile.mktemp()
# self.delete_cache = True
#else:
# self.delete_cache = False
self.delete_cache = False
self.cache_dir = cache_dir
self.cache_files = []
self.mem_cache = {}
# create the cache dir
if cache_dir:
try:
os.makedirs(cache_dir)
except OSError: pass
def __del__(self):
self.Close()
def _IncludeParams(self, filename):
includes = self.includes[:]
filedir = os.path.dirname(filename)
if not filedir:
filedir = '.'
includes.insert(0, filedir)
includes = ['-I "%s"' % self.Unixfy(x) for x in includes]
return ' '.join(includes)
def _DefineParams(self):
defines = ['-D "%s"' % x for x in self.defines]
return ' '.join(defines)
def FindHeader(self, header):
if os.path.isfile(header):
return header
for path in self.includes:
filename = os.path.join(path, header)
if os.path.isfile(filename):
return filename
else:
name = os.path.basename(header)
raise RuntimeError, 'Header file "%s" not found!' % name
def AppendTail(self, filename, tail):
'''Creates a temporary file, appends the text tail to it, and returns
the filename of the file.
'''
if hasattr(tempfile, 'mkstemp'):
f_no, temp = tempfile.mkstemp('.h')
f = file(temp, 'a')
os.close(f_no)
else:
temp = tempfile.mktemp('.h')
f = file(temp, 'a')
f.write('#include "%s"\n\n' % os.path.abspath(filename))
f.write(tail)
f.write('\n')
f.close()
return temp
def Unixfy(self, path):
return path.replace('\\', '/')
def ParseWithGCCXML(self, header, tail):
'''Parses the given header using gccxml and GCCXMLParser.
'''
header = self.FindHeader(header)
if tail:
filename = self.AppendTail(header, tail)
else:
filename = header
xmlfile = tempfile.mktemp('.xml')
try:
# get the params
includes = self._IncludeParams(filename)
defines = self._DefineParams()
# call gccxml
cmd = '%s %s %s "%s" -fxml=%s'
filename = self.Unixfy(filename)
xmlfile = self.Unixfy(xmlfile)
status = os.system(cmd % (self.gccxml_path, includes, defines, filename, xmlfile))
if status != 0 or not os.path.isfile(xmlfile):
raise CppParserError, 'Error executing gccxml'
# parse the resulting xml
declarations = ParseDeclarations(xmlfile)
# make the declarations' location to point to the original file
if tail:
for decl in declarations:
decl_filename = os.path.normpath(os.path.normcase(decl.location[0]))
filename = os.path.normpath(os.path.normcase(filename))
if decl_filename == filename:
decl.location = header, decl.location[1]
# return the declarations
return declarations
finally:
if settings.DEBUG and os.path.isfile(xmlfile):
debugname = os.path.basename(header)
debugname = os.path.splitext(debugname)[0] + '.xml'
print 'DEBUG:', debugname
shutil.copy(xmlfile, debugname)
# delete the temporary files
try:
os.remove(xmlfile)
if tail:
os.remove(filename)
except OSError: pass
def Parse(self, header, interface, tail=None):
'''Parses the given filename related to the given interface and returns
the (declarations, headerfile). The header returned is normally the
same as the given to this method (except that it is the full path),
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
gccxml. This temp filename is then returned.
'''
if tail is None:
tail = ''
tail = tail.strip()
declarations = self.GetCache(header, interface, tail)
if declarations is None:
declarations = self.ParseWithGCCXML(header, tail)
self.CreateCache(header, interface, tail, declarations)
header_fullpath = os.path.abspath(self.FindHeader(header))
return declarations, header_fullpath
def CacheFileName(self, interface):
interface_name = os.path.basename(interface)
cache_file = os.path.splitext(interface_name)[0] + '.pystec'
cache_file = os.path.join(self.cache_dir, cache_file)
return cache_file
def GetCache(self, header, interface, tail):
key = (header, interface, tail)
# try memory cache first
if key in self.mem_cache:
return self.mem_cache[key]
# get the cache from the disk
if self.cache_dir is None:
return None
header = self.FindHeader(header)
cache_file = self.CacheFileName(interface)
if os.path.isfile(cache_file):
f = file(cache_file, 'rb')
try:
version = load(f)
if version != self.version:
return None
cache = load(f)
if cache.has_key(key):
self.cache_files.append(cache_file)
return cache[key]
else:
return None
finally:
f.close()
else:
return None
def CreateCache(self, header, interface, tail, declarations):
key = (header, interface, tail)
# our memory cache only holds one item
self.mem_cache.clear()
self.mem_cache[key] = declarations
# save the cache in the disk
if self.cache_dir is None:
return
header = self.FindHeader(header)
cache_file = self.CacheFileName(interface)
if os.path.isfile(cache_file):
f = file(cache_file, 'rb')
try:
version = load(f)
cache = load(f)
finally:
f.close()
else:
cache = {}
cache[key] = declarations
self.cache_files.append(cache_file)
f = file(cache_file, 'wb')
try:
dump(self.version, f, 1)
dump(cache, f, 1)
finally:
f.close()
return cache_file
def Close(self):
if self.delete_cache and self.cache_files:
for filename in self.cache_files:
try:
os.remove(filename)
except OSError:
pass
self.cache_files = []
shutil.rmtree(self.cache_dir)

View File

@@ -1,58 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from Exporter import Exporter
from settings import *
import utils
#==============================================================================
# EnumExporter
#==============================================================================
class EnumExporter(Exporter):
'Exports enumerators'
def __init__(self, info):
Exporter.__init__(self, info)
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
if self.declarations:
self.enum = self.GetDeclaration(self.info.name)
else:
self.enum = None
def Export(self, codeunit, exported_names):
if self.info.exclude:
return
indent = self.INDENT
in_indent = self.INDENT*2
rename = self.info.rename or self.enum.name
full_name = self.enum.FullName()
unnamed_enum = False
if rename.startswith('$_') or rename.startswith('._'):
unnamed_enum = True
code = ''
if not unnamed_enum:
code += indent + namespaces.python
code += '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)
if not unnamed_enum:
code += in_indent + '.value("%s", %s)\n' % (rename, value_fullname)
else:
code += indent + namespaces.python
code += 'scope().attr("%s") = (int)%s;\n' % (rename, value_fullname )
if self.info.export_values and not unnamed_enum:
code += in_indent + '.export_values()\n'
if not unnamed_enum:
code += indent + ';\n'
code += '\n'
codeunit.Write('module', code)
exported_names[self.enum.FullName()] = 1
def Name(self):
return self.info.name

View File

@@ -1,94 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import os.path
#==============================================================================
# Exporter
#==============================================================================
class Exporter(object):
'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
self.interface_file = None
self.declarations = []
def Name(self):
raise NotImplementedError(self.__class__.__name__)
def Tail(self):
return self.parser_tail
def Parse(self, parser):
self.parser = parser
header = self.info.include
tail = self.parser_tail
declarations, parser_header = parser.parse(header, tail)
self.parser_header = parser_header
self.SetDeclarations(declarations)
def SetParsedHeader(self, parsed_header):
self.parser_header = parsed_header
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 GetDeclarations(self, fullname):
decls = []
for decl in self.declarations:
if decl.FullName() == fullname:
decls.append(decl)
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 string that uniquely identifies this instance. All
exporters will be sorted by Order before being exported.
'''
return 0, self.info.name
def Header(self):
return self.info.include
def __eq__(self, other):
return type(self) is type(other) and self.Name() == other.Name() \
and self.interface_file == other.interface_file
def __ne__(self, other):
return not self == other

View File

@@ -1,92 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from Exporter import Exporter
from policies import *
from declarations import *
from settings import *
import utils
import exporterutils
#==============================================================================
# FunctionExporter
#==============================================================================
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):
if not self.info.exclude:
decls = self.GetDeclarations(self.info.name)
for decl in decls:
self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy)
self.ExportDeclaration(decl, len(decls) == 1, codeunit)
self.ExportOpaquePointer(decl, codeunit)
self.GenerateOverloads(decls, codeunit)
exported_names[self.Name()] = 1
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()
else:
pointer = decl.PointerDeclaration()
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', wrapper.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 ''
def ExportOpaquePointer(self, function, codeunit):
if self.info.policy == return_value_policy(return_opaque_pointer):
typename = function.result.name
macro = exporterutils.EspecializeTypeID(typename)
if macro:
codeunit.Write('declaration-outside', macro)
def Name(self):
return self.info.name

View File

@@ -1,478 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from declarations import *
try:
# try to use internal elementtree
from xml.etree.cElementTree import ElementTree
except ImportError:
# try to use cElementTree if avaiable
try:
from cElementTree import ElementTree
except ImportError:
# fall back to the normal elementtree
from elementtree.ElementTree import ElementTree
from xml.parsers.expat import ExpatError
from copy import deepcopy
from utils import enumerate
#==============================================================================
# Exceptions
#==============================================================================
class InvalidXMLError(Exception): pass
class ParserError(Exception): pass
class InvalidContextError(ParserError): pass
#==============================================================================
# GCCXMLParser
#==============================================================================
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 = []
self._names = {}
# 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):
if decl.FullName() in self._names:
decl.is_unique= False
for d in self.declarations:
if d.FullName() == decl.FullName():
d.is_unique = False
self._names[decl.FullName()] = 0
self.declarations.append(decl)
def ParseElement(self, id, element):
method = 'Parse' + element.tag
if hasattr(self, method):
func = getattr(self, method)
func(id, element)
else:
self.ParseUnknown(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):
def Check(id, feature):
pos = id.find(feature)
if pos != -1:
id = id[:pos] + id[pos+1:]
return True, id
else:
return False, id
const, id = Check(id, 'c')
volatile, id = Check(id, 'v')
restricted, id = Check(id, 'r')
decl = self.GetDecl(id)
if isinstance(decl, Type):
res = deepcopy(decl)
if const:
res.const = const
if volatile:
res.volatile = volatile
if restricted:
res.restricted = restricted
else:
res = Type(decl.FullName(), const)
res.volatile = volatile
res.restricted = restricted
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 ParseUnknown(self, id, element):
name = '__Unknown_Element_%s' % id
decl = Unknown(name)
self.Update(id, decl)
def ParseNamespace(self, id, element):
namespace = element.get('name')
context = element.get('context')
if context:
outer = self.GetDecl(context)
if not outer.endswith('::'):
outer += '::'
namespace = outer + 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.
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 GetExceptions(self, exception_list):
if exception_list is None:
return None
exceptions = []
for t in exception_list.split():
exceptions.append(self.GetType(t))
return exceptions
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)
incomplete = bool(int(element.get('incomplete', 0)))
throws = self.GetExceptions(element.get('throw', None))
function = functionType(name, namespace, returns, params, throws)
function.location = location
self.AddDecl(function)
self.Update(id, function)
def ParseOperatorFunction(self, id, element):
self.ParseFunction(id, element, Operator)
def GetHierarchy(self, bases):
'''Parses the string "bases" from the xml into a list of tuples of Base
instances. The first tuple is the most direct inheritance, and then it
goes up in the hierarchy.
'''
if bases is None:
return []
base_names = bases.split()
this_level = []
next_levels = []
for base in base_names:
# get the visibility
split = base.split(':')
if len(split) == 2:
visib = split[0]
base = split[1]
else:
visib = Scope.public
decl = self.GetDecl(base)
if not isinstance(decl, Class):
# on windows, there are some classes which "bases" points to an
# "Unimplemented" tag, but we are not interested in this classes
# anyway
continue
base = Base(decl.FullName(), visib)
this_level.append(base)
# normalize with the other levels
for index, level in enumerate(decl.hierarchy):
if index < len(next_levels):
next_levels[index] = next_levels[index] + level
else:
next_levels.append(level)
hierarchy = []
if this_level:
hierarchy.append(tuple(this_level))
if next_levels:
hierarchy.extend(next_levels)
return hierarchy
def GetMembers(self, member_list):
# members must be a string with the ids of the members
if member_list is None:
return []
members = []
for member in member_list.split():
decl = self.GetDecl(member)
if type(decl) in Class.ValidMemberTypes():
members.append(decl)
return members
def ParseClass(self, id, element):
name = element.get('name')
abstract = bool(int(element.get('abstract', '0')))
location = self.GetLocation(element.get('location'))
context = self.GetDecl(element.get('context'))
incomplete = bool(int(element.get('incomplete', 0)))
if isinstance(context, str):
class_ = Class(name, context, [], abstract)
else:
# a nested class
visib = element.get('access', Scope.public)
class_ = NestedClass(
name, context.FullName(), visib, [], abstract)
class_.incomplete = incomplete
# we have to add the declaration of the class before trying
# to parse its members and bases, to avoid recursion.
self.AddDecl(class_)
class_.location = location
self.Update(id, class_)
# now we can get the members and the bases
class_.hierarchy = self.GetHierarchy(element.get('bases'))
if class_.hierarchy:
class_.bases = class_.hierarchy[0]
members = self.GetMembers(element.get('members'))
for member in members:
class_.AddMember(member)
def ParseStruct(self, id, element):
self.ParseClass(id, element)
FUNDAMENTAL_RENAME = {
'long long int' : 'boost::int64_t',
'long long unsigned int' : 'boost::uint64_t',
}
def ParseFundamentalType(self, id, element):
name = element.get('name')
name = self.FUNDAMENTAL_RENAME.get(name, 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')
array = ArrayType(type.name, type.const, min, max)
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, type.suffix)
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, type.suffix)
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'))
throws = self.GetExceptions(element.get('throw', None))
params = self.GetArguments(element)
method = methodType(
name, classname, result, params, visib, virtual, abstract, static, const, throws)
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)
artificial = element.get('artificial', False)
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.GetType(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'))
incomplete = bool(int(element.get('incomplete', 0)))
if isinstance(context, str):
enum = Enumeration(name, context)
else:
visib = element.get('access', Scope.public)
enum = ClassEnumeration(name, context.FullName(), visib)
self.AddDecl(enum)
enum.location = location
for child in element:
if child.tag == 'EnumValue':
name = child.get('name')
value = int(child.get('init'))
enum.values[name] = value
enum.incomplete = incomplete
self.Update(id, enum)
def ParseDeclarations(filename):
'Returns a list of the top declarations found in the gcc_xml file.'
parser = GCCXMLParser()
parser.Parse(filename)
return parser.Declarations()
if __name__ == '__main__':
ParseDeclarations(r'D:\Programming\Libraries\boost-cvs\boost\libs\python\pyste\example\test.xml')

View File

@@ -1,81 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from Exporter import Exporter
from ClassExporter import ClassExporter
from FunctionExporter import FunctionExporter
from EnumExporter import EnumExporter
from VarExporter import VarExporter
from infos import *
from declarations import *
import os.path
import exporters
import MultipleCodeUnit
#==============================================================================
# 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 IsInternalName(self, name):
'''Returns true if the given name looks like a internal compiler
structure'''
return name.startswith('_')
def Export(self, codeunit, exported_names):
header = os.path.normpath(self.parser_header)
for decl in self.declarations:
# check if this declaration is in the header
location = os.path.abspath(decl.location[0])
if location == header and not self.IsInternalName(decl.name):
# ok, check the type of the declaration and export it accordingly
self.HandleDeclaration(decl, codeunit, exported_names)
def HandleDeclaration(self, decl, codeunit, exported_names):
'''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,
Variable : VarExporter,
}
exporter_class = dispatch_table.get(type(decl))
if exporter_class is not None:
self.HandleExporter(decl, exporter_class, codeunit, exported_names)
def HandleExporter(self, decl, exporter_type, codeunit, exported_names):
# only export complete declarations
if not decl.incomplete:
info = self.info[decl.name]
info.name = decl.FullName()
info.include = self.info.include
exporter = exporter_type(info)
exporter.SetDeclarations(self.declarations)
exporter.SetParsedHeader(self.parser_header)
if isinstance(codeunit, MultipleCodeUnit.MultipleCodeUnit):
codeunit.SetCurrent(self.interface_file, exporter.Name())
else:
codeunit.SetCurrent(exporter.Name())
exporter.GenerateCode(codeunit, exported_names)
def Name(self):
return self.info.include

View File

@@ -1,135 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from SingleCodeUnit import SingleCodeUnit
import os
import utils
from SmartFile import SmartFile
#==============================================================================
# MultipleCodeUnit
#==============================================================================
class MultipleCodeUnit(object):
'''
Represents a bunch of cpp files, where each cpp file represents a header
to be exported by pyste. Another cpp, named <module>.cpp is created too.
'''
def __init__(self, modulename, outdir):
self.modulename = modulename
self.outdir = outdir
self.codeunits = {} # maps from a (filename, function) to a SingleCodeUnit
self.functions = []
self._current = None
self.all = SingleCodeUnit(None, None)
def _FunctionName(self, interface_file):
name = os.path.splitext(interface_file)[0]
return 'Export_%s' % utils.makeid(name)
def _FileName(self, interface_file):
filename = os.path.basename(interface_file)
filename = '_%s.cpp' % os.path.splitext(filename)[0]
return os.path.join(self.outdir, filename)
def SetCurrent(self, interface_file, export_name):
'Changes the current code unit'
if export_name is None:
self._current = None
elif export_name is '__all__':
self._current = self.all
else:
filename = self._FileName(interface_file)
function = self._FunctionName(interface_file)
try:
codeunit = self.codeunits[filename]
except KeyError:
codeunit = SingleCodeUnit(None, filename)
codeunit.module_definition = 'void %s()' % function
self.codeunits[filename] = codeunit
if function not in self.functions:
self.functions.append(function)
self._current = codeunit
def Current(self):
return self._current
current = property(Current, SetCurrent)
def Write(self, section, code):
if self._current is not None:
self.current.Write(section, code)
def Section(self, section):
if self._current is not None:
return self.current.Section(section)
def _CreateOutputDir(self):
try:
os.mkdir(self.outdir)
except OSError: pass # already created
def Save(self):
# create the directory where all the files will go
self._CreateOutputDir();
# order all code units by filename, and merge them all
codeunits = {} # filename => list of codeunits
# While ordering all code units by file name, the first code
# unit in the list of code units is used as the main unit
# which dumps all the include, declaration and
# declaration-outside sections at the top of the file.
for filename, codeunit in self.codeunits.items():
if filename not in codeunits:
# this codeunit is the main codeunit.
codeunits[filename] = [codeunit]
codeunit.Merge(self.all)
else:
main_unit = codeunits[filename][0]
for section in ('include', 'declaration', 'declaration-outside'):
main_unit.code[section] = main_unit.code[section] + codeunit.code[section]
codeunit.code[section] = ''
codeunits[filename].append(codeunit)
# Now write all the codeunits appending them correctly.
for file_units in codeunits.values():
append = False
for codeunit in file_units:
codeunit.Save(append)
if not append:
append = True
def GenerateMain(self, interfaces):
# generate the main cpp
filename = os.path.join(self.outdir, '_main.cpp')
fout = SmartFile(filename, 'w')
fout.write(utils.left_equals('Include'))
fout.write('#include <boost/python/module.hpp>\n\n')
fout.write(utils.left_equals('Exports'))
functions = [self._FunctionName(x) for x in interfaces]
for function in functions:
fout.write('void %s();\n' % function)
fout.write('\n')
fout.write(utils.left_equals('Module'))
fout.write('BOOST_PYTHON_MODULE(%s)\n' % self.modulename)
fout.write('{\n')
indent = ' ' * 4
for function in functions:
fout.write(indent)
fout.write('%s();\n' % function)
fout.write('}\n')

View File

@@ -1,121 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from settings import namespaces
import settings
from utils import remove_duplicated_lines, left_equals
from SmartFile import SmartFile
#==============================================================================
# SingleCodeUnit
#==============================================================================
class SingleCodeUnit:
'''
Represents a cpp file, where other objects can write in one of the
predefined sections.
The avaiable sections are:
pchinclude - The pre-compiled header area
include - The include area of the cpp file
declaration - The part before the module definition
module - Inside the BOOST_PYTHON_MODULE macro
'''
def __init__(self, modulename, filename):
self.modulename = modulename
self.filename = filename
# define the avaiable sections
self.code = {}
# include section
self.code['pchinclude'] = ''
# include section
self.code['include'] = ''
# declaration section (inside namespace)
self.code['declaration'] = ''
# declaration (outside namespace)
self.code['declaration-outside'] = ''
# inside BOOST_PYTHON_MACRO
self.code['module'] = ''
# create the default module definition
self.module_definition = 'BOOST_PYTHON_MODULE(%s)' % modulename
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 Merge(self, other):
for section in ('include', 'declaration', 'declaration-outside', 'module'):
self.code[section] = self.code[section] + other.code[section]
def Section(self, section):
return self.code[section]
def SetCurrent(self, *args):
pass
def Current(self):
pass
def Save(self, append=False):
'Writes this code unit to the filename'
space = '\n\n'
if not append:
flag = 'w'
else:
flag = 'a'
fout = SmartFile(self.filename, flag)
fout.write('\n')
# includes
# boost.python header
if self.code['pchinclude']:
fout.write(left_equals('PCH'))
fout.write(self.code['pchinclude']+'\n')
fout.write('#ifdef _MSC_VER\n')
fout.write('#pragma hdrstop\n')
fout.write('#endif\n')
else:
fout.write(left_equals('Boost Includes'))
fout.write('#include <boost/python.hpp>\n')
# include numerical boost for int64 definitions
fout.write('#include <boost/cstdint.hpp>\n')
fout.write('\n')
# other includes
if self.code['include']:
fout.write(left_equals('Includes'))
includes = remove_duplicated_lines(self.code['include'])
fout.write(includes)
fout.write(space)
# using
if settings.USING_BOOST_NS and not append:
fout.write(left_equals('Using'))
fout.write('using namespace boost::python;\n\n')
# declarations
declaration = self.code['declaration']
declaration_outside = self.code['declaration-outside']
if declaration_outside or declaration:
fout.write(left_equals('Declarations'))
if declaration_outside:
fout.write(declaration_outside + '\n\n')
if declaration:
pyste_namespace = namespaces.pyste[:-2]
fout.write('namespace %s {\n\n' % pyste_namespace)
fout.write(declaration)
fout.write('\n}// namespace %s\n' % pyste_namespace)
fout.write(space)
# module
fout.write(left_equals('Module'))
fout.write(self.module_definition + '\n')
fout.write('{\n')
fout.write(self.code['module'])
fout.write('}\n\n')
fout.close()

View File

@@ -1,60 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import os
import md5
#==============================================================================
# SmartFile
#==============================================================================
class SmartFile(object):
'''
A file-like object used for writing files. The given file will only be
actually written to disk if there's not a file with the same name, or if
the existing file is *different* from the file to be written.
'''
def __init__(self, filename, mode='w'):
self.filename = filename
self.mode = mode
self._contents = []
self._closed = False
def __del__(self):
if not self._closed:
self.close()
def write(self, string):
self._contents.append(string)
def _dowrite(self, contents):
f = file(self.filename, self.mode)
f.write(contents)
f.close()
def _GetMD5(self, string):
return md5.new(string).digest()
def close(self):
# if the filename doesn't exist, write the file right away
this_contents = ''.join(self._contents)
if not os.path.isfile(self.filename):
self._dowrite(this_contents)
else:
# read the contents of the file already in disk
f = file(self.filename)
other_contents = f.read()
f.close()
# test the md5 for both files
this_md5 = self._GetMD5(this_contents)
other_md5 = self._GetMD5(other_contents)
if this_md5 != other_md5:
self._dowrite(this_contents)
self._closed = True

View File

@@ -1,40 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from Exporter import Exporter
from settings import *
import utils
#==============================================================================
# VarExporter
#==============================================================================
class VarExporter(Exporter):
'''Exports a global variable.
'''
def __init__(self, info):
Exporter.__init__(self, info)
def Export(self, codeunit, exported_names):
if self.info.exclude: return
decl = self.GetDeclaration(self.info.name)
if not decl.type.const:
msg = '---> Warning: The global variable "%s" is non-const:\n' \
' changes in Python will not reflect in C++.'
print msg % self.info.name
print
rename = self.info.rename or self.info.name
code = self.INDENT + namespaces.python
code += 'scope().attr("%s") = %s;\n' % (rename, self.info.name)
codeunit.Write('module', code)
def Order(self):
return 0, self.info.name
def Name(self):
return self.info.name

View File

@@ -1,6 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -1,653 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
'''
Defines classes that represent declarations found in C++ header files.
'''
# version indicates the version of the declarations. Whenever a declaration
# changes, this variable should be updated, so that the caches can be rebuilt
# automatically
version = '1.0'
#==============================================================================
# Declaration
#==============================================================================
class Declaration(object):
'''Base class for all declarations.
@ivar name: The name of the declaration.
@ivar namespace: The namespace of the declaration.
'''
def __init__(self, name, namespace):
'''
@type name: string
@param name: The name of this declaration
@type namespace: string
@param namespace: the full namespace where this declaration resides.
'''
self.name = name
self.namespace = namespace
self.location = '', -1 # (filename, line)
self.incomplete = False
self.is_unique = True
def FullName(self):
'''
Returns the full qualified name: "boost::inner::Test"
@rtype: string
@return: The full name of the declaration.
'''
namespace = self.namespace or ''
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 Class(Declaration):
'''
Represents a C++ class or struct. Iteration through it yields its members.
@type abstract: bool
@ivar abstract: if the class has any abstract methods.
@type bases: tuple
@ivar bases: tuple with L{Base} instances, representing the most direct
inheritance.
@type hierarchy: list
@ivar hierarchy: a list of tuples of L{Base} instances, representing
the entire hierarchy tree of this object. The first tuple is the parent
classes, and the other ones go up in the hierarchy.
'''
def __init__(self, name, namespace, members, abstract):
Declaration.__init__(self, name, namespace)
self.__members = members
self.__member_names = {}
self.abstract = abstract
self.bases = ()
self.hierarchy = ()
self.operator = {}
def __iter__(self):
'''iterates through the class' members.
'''
return iter(self.__members)
def Constructors(self, publics_only=True):
'''Returns a list of the constructors for this class.
@rtype: list
'''
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):
'''Returns true if this class has a public copy constructor.
@rtype: bool
'''
for cons in self.Constructors():
if cons.IsCopy():
return True
return False
def HasDefaultConstructor(self):
'''Returns true if this class has a public default constructor.
@rtype: bool
'''
for cons in self.Constructors():
if cons.IsDefault():
return True
return False
def AddMember(self, member):
if member.name in self.__member_names:
member.is_unique = False
for m in self:
if m.name == member.name:
m.is_unique = False
else:
member.is_unique = True
self.__member_names[member.name] = 1
self.__members.append(member)
if isinstance(member, ClassOperator):
self.operator[member.name] = member
def ValidMemberTypes():
return (NestedClass, Method, Constructor, Destructor, ClassVariable,
ClassOperator, ConverterOperator, ClassEnumeration)
ValidMemberTypes = staticmethod(ValidMemberTypes)
#==============================================================================
# NestedClass
#==============================================================================
class NestedClass(Class):
'''The declaration of a class/struct inside another class/struct.
@type class: string
@ivar class: fullname of the class where this class is contained.
@type visibility: L{Scope}
@ivar visibility: the visibility of this class.
'''
def __init__(self, name, class_, visib, members, abstract):
Class.__init__(self, name, None, members, abstract)
self.class_ = class_
self.visibility = visib
def FullName(self):
'''The full name of this class, like ns::outer::inner.
@rtype: string
'''
return '%s::%s' % (self.class_, self.name)
#==============================================================================
# Scope
#==============================================================================
class Scope:
'''Used to represent the visibility of various members inside a class.
@cvar public: public visibility
@cvar private: private visibility
@cvar protected: protected visibility
'''
public = 'public'
private = 'private'
protected = 'protected'
#==============================================================================
# Base
#==============================================================================
class Base:
'''Represents a base class of another class.
@ivar _name: the full name of the base class.
@ivar _visibility: the visibility of the derivation.
'''
def __init__(self, name, visibility=Scope.public):
self.name = name
self.visibility = visibility
#==============================================================================
# Function
#==============================================================================
class Function(Declaration):
'''The declaration of a function.
@ivar _result: instance of L{Type} or None.
@ivar _parameters: list of L{Type} instances.
@ivar _throws: exception specifiers or None
'''
def __init__(self, name, namespace, result, params, throws=None):
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
# the exception specification
self.throws = throws
def Exceptions(self):
if self.throws is None:
return ""
else:
return " throw(%s)" % ', '.join ([x.FullName() for x in self.throws])
def PointerDeclaration(self, force=False):
'''Returns a declaration of a pointer to this function.
@param force: If True, returns a complete pointer declaration regardless
if this function is unique or not.
'''
if self.is_unique and not force:
return '&%s' % self.FullName()
else:
result = self.result.FullName()
params = ', '.join([x.FullName() for x in self.parameters])
return '(%s (*)(%s)%s)&%s' % (result, params, self.Exceptions(), 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)
#==============================================================================
# Operator
#==============================================================================
class Operator(Function):
'''The declaration of a custom operator. Its name is the same as the
operator name in C++, ie, the name of the declaration "operator+(..)" is
"+".
'''
def FullName(self):
namespace = self.namespace or ''
if not namespace.endswith('::'):
namespace += '::'
return namespace + 'operator' + self.name
#==============================================================================
# Method
#==============================================================================
class Method(Function):
'''The declaration of a method.
@ivar _visibility: the visibility of this method.
@ivar _virtual: if this method is declared as virtual.
@ivar _abstract: if this method is virtual but has no default implementation.
@ivar _static: if this method is static.
@ivar _class: the full name of the class where this method was declared.
@ivar _const: if this method is declared as const.
@ivar _throws: list of exception specificiers or None
'''
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const, throws=None):
Function.__init__(self, name, None, result, params, throws)
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, force=False):
'''Returns a declaration of a pointer to this member function.
@param force: If True, returns a complete pointer declaration regardless
if this function is unique or not.
'''
if self.static:
# static methods are like normal functions
return Function.PointerDeclaration(self, force)
if self.is_unique and not force:
return '&%s' % self.FullName()
else:
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)&%s' %\
(result, self.class_, params, const, self.Exceptions(), self.FullName())
#==============================================================================
# Constructor
#==============================================================================
class Constructor(Method):
'''A class' constructor.
'''
def __init__(self, name, class_, params, visib):
Method.__init__(self, name, class_, None, params, visib, False, False, False, False)
def IsDefault(self):
'''Returns True if this constructor is a default constructor.
'''
return len(self.parameters) == 0 and self.visibility == Scope.public
def IsCopy(self):
'''Returns True if this constructor is a copy constructor.
'''
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)
is_public = self.visibility == Scope.public
return param_reference and class_as_param and param.const and is_public
def PointerDeclaration(self, force=False):
return ''
#==============================================================================
# Destructor
#==============================================================================
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
def PointerDeclaration(self, force=False):
return ''
#==============================================================================
# ClassOperator
#==============================================================================
class ClassOperator(Method):
'A custom operator in a class.'
def FullName(self):
return self.class_ + '::operator ' + self.name
#==============================================================================
# ConverterOperator
#==============================================================================
class ConverterOperator(ClassOperator):
'An operator in the form "operator OtherClass()".'
def FullName(self):
return self.class_ + '::operator ' + self.result.FullName()
#==============================================================================
# Type
#==============================================================================
class Type(Declaration):
'''Represents the type of a variable or parameter.
@ivar _const: if the type is constant.
@ivar _default: if this type has a default value associated with it.
@ivar _volatile: if this type was declared with the keyword volatile.
@ivar _restricted: if this type was declared with the keyword restricted.
@ivar _suffix: Suffix to get the full type name. '*' for pointers, for
example.
'''
def __init__(self, name, const=False, default=None, suffix=''):
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
self.restricted = False
self.suffix = suffix
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 + self.suffix
#==============================================================================
# ArrayType
#==============================================================================
class ArrayType(Type):
'''Represents an array.
@ivar min: the lower bound of the array, usually 0. Can be None.
@ivar max: the upper bound of the array. Can be None.
'''
def __init__(self, name, const, min, max):
'min and max can be None.'
Type.__init__(self, name, const)
self.min = min
self.max = max
#==============================================================================
# ReferenceType
#==============================================================================
class ReferenceType(Type):
'''A reference type.'''
def __init__(self, name, const=False, default=None, expandRef=True, suffix=''):
Type.__init__(self, name, const, default)
if expandRef:
self.suffix = suffix + '&'
#==============================================================================
# PointerType
#==============================================================================
class PointerType(Type):
'A pointer type.'
def __init__(self, name, const=False, default=None, expandPointer=False, suffix=''):
Type.__init__(self, name, const, default)
if expandPointer:
self.suffix = suffix + '*'
#==============================================================================
# FundamentalType
#==============================================================================
class FundamentalType(Type):
'One of the fundamental types, like int, void, etc.'
def __init__(self, name, const=False, default=None):
Type.__init__(self, name, const, default)
#==============================================================================
# FunctionType
#==============================================================================
class FunctionType(Type):
'''A pointer to a function.
@ivar _result: the return value
@ivar _parameters: a list of Types, indicating the parameters of the function.
@ivar _name: the name of the function.
'''
def __init__(self, result, parameters):
Type.__init__(self, '', False)
self.result = result
self.parameters = parameters
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
#==============================================================================
# MethodType
#==============================================================================
class MethodType(FunctionType):
'''A pointer to a member function of a class.
@ivar _class: The fullname of the class that the method belongs to.
'''
def __init__(self, result, parameters, class_):
self.class_ = class_
FunctionType.__init__(self, result, parameters)
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
#==============================================================================
# Variable
#==============================================================================
class Variable(Declaration):
'''Represents a global variable.
@type _type: L{Type}
@ivar _type: The type of the variable.
'''
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
self.type = type
#==============================================================================
# ClassVariable
#==============================================================================
class ClassVariable(Variable):
'''Represents a class variable.
@type _visibility: L{Scope}
@ivar _visibility: The visibility of this variable within the class.
@type _static: bool
@ivar _static: Indicates if the variable is static.
@ivar _class: Full name of the class that this variable belongs to.
'''
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
#==============================================================================
# Enumeration
#==============================================================================
class Enumeration(Declaration):
'''Represents an enum.
@type _values: dict of str => int
@ivar _values: holds the values for this enum.
'''
def __init__(self, name, namespace):
Declaration.__init__(self, name, namespace)
self.values = {} # dict of str => int
def ValueFullName(self, name):
'''Returns the full name for a value in the enum.
'''
assert name in self.values
namespace = self.namespace
if namespace:
namespace += '::'
return namespace + name
#==============================================================================
# ClassEnumeration
#==============================================================================
class ClassEnumeration(Enumeration):
'''Represents an enum inside a class.
@ivar _class: The full name of the class where this enum belongs.
@ivar _visibility: The visibility of this enum inside his class.
'''
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)
#==============================================================================
# Typedef
#==============================================================================
class Typedef(Declaration):
'''A Typedef declaration.
@type _type: L{Type}
@ivar _type: The type of the typedef.
@type _visibility: L{Scope}
@ivar _visibility: The visibility of this typedef.
'''
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
self.type = type
self.visibility = Scope.public
#==============================================================================
# Unknown
#==============================================================================
class Unknown(Declaration):
'''A declaration that Pyste does not know how to handle.
'''
def __init__(self, name):
Declaration.__init__(self, name, None)

View File

@@ -1,12 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# a list of Exporter instances
exporters = []
current_interface = None # the current interface file being processed
importing = False # whetever we are now importing a pyste file.
# exporters created here shouldn't export themselves

View File

@@ -1,87 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
'''
Various helpers for interface files.
'''
from settings import *
from policies import *
from declarations import *
#==============================================================================
# FunctionWrapper
#==============================================================================
class FunctionWrapper(object):
'''Holds information about a wrapper for a function or a method. It is
divided 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
_printed_warnings = {} # used to avoid double-prints of warnings
#==============================================================================
# HandlePolicy
#==============================================================================
def HandlePolicy(function, policy):
'''Show a warning to the user if the function needs a policy and doesn't
have one. Return a policy to the function, which is the given policy itself
if it is not None, or a default policy for this method.
'''
def IsString(type):
'Return True if the Type instance can be considered a string'
return type.FullName() == 'const char*'
def IsPyObject(type):
return type.FullName() == '_object *' # internal name of PyObject
result = function.result
# if the function returns const char*, a policy is not needed
if IsString(result) or IsPyObject(result):
return policy
# if returns a const T&, set the default policy
if policy is None and result.const and isinstance(result, ReferenceType):
policy = return_value_policy(copy_const_reference)
# basic test if the result type demands a policy
needs_policy = isinstance(result, (ReferenceType, PointerType))
# show a warning to the user, if needed
if needs_policy and policy is None:
global _printed_warnings
warning = '---> Error: %s returns a pointer or a reference, ' \
'but no policy was specified.' % function.FullName()
if warning not in _printed_warnings:
print warning
print
# avoid double prints of the same warning
_printed_warnings[warning] = 1
return policy
#==============================================================================
# EspecializeTypeID
#==============================================================================
_exported_type_ids = {}
def EspecializeTypeID(typename):
global _exported_type_ids
macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)\n' % typename
if macro not in _exported_type_ids:
_exported_type_ids[macro] = 1
return macro
else:
return None

View File

@@ -1,259 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import os.path
import copy
import exporters
from ClassExporter import ClassExporter
from FunctionExporter import FunctionExporter
from EnumExporter import EnumExporter
from HeaderExporter import HeaderExporter
from VarExporter import VarExporter
from CodeExporter import CodeExporter
from exporterutils import FunctionWrapper
from utils import makeid
import warnings
#==============================================================================
# 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
def AddExporter(self, exporter):
# this was causing a much serious bug, as reported by Niall Douglas:
# another solution must be found!
#if not exporters.importing:
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# FunctionInfo
#==============================================================================
class FunctionInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherOption=None,
exporter_class = FunctionExporter):
DeclarationInfo.__init__(self, otherOption)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
# create a FunctionExporter
exporter = exporter_class(InfoWrapper(self), tail)
self.AddExporter(exporter)
#==============================================================================
# ClassInfo
#==============================================================================
class ClassInfo(DeclarationInfo):
def __init__(self, name, include, tail=None, otherInfo=None,
exporter_class = ClassExporter):
DeclarationInfo.__init__(self, otherInfo)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
# create a ClassExporter
exporter = exporter_class(InfoWrapper(self), tail)
self.AddExporter(exporter)
#==============================================================================
# templates
#==============================================================================
def GenerateName(name, type_list):
name = name.replace('::', '_')
names = [name] + type_list
return makeid('_'.join(names))
class ClassTemplateInfo(DeclarationInfo):
def __init__(self, name, include,
exporter_class = ClassExporter):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
self._exporter_class = exporter_class
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,
exporter_class = self._exporter_class)
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, exporter_class = EnumExporter):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
self._Attribute('exclude', False)
self._Attribute('export_values', False)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(exporter)
#==============================================================================
# HeaderInfo
#==============================================================================
class HeaderInfo(DeclarationInfo):
def __init__(self, include, exporter_class = HeaderExporter):
warnings.warn('AllFromHeader is not working in all cases in the current version.')
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(exporter)
#==============================================================================
# VarInfo
#==============================================================================
class VarInfo(DeclarationInfo):
def __init__(self, name, include, exporter_class = VarExporter):
DeclarationInfo.__init__(self)
self._Attribute('name', name)
self._Attribute('include', include)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(exporter)
#==============================================================================
# CodeInfo
#==============================================================================
class CodeInfo(DeclarationInfo):
def __init__(self, code, section, exporter_class = CodeExporter):
DeclarationInfo.__init__(self)
self._Attribute('code', code)
self._Attribute('section', section)
exporter = exporter_class(InfoWrapper(self))
self.AddExporter(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(info):
info._Attribute('exclude', True)
def set_policy(info, policy):
info._Attribute('policy', policy)
def rename(info, name):
info._Attribute('rename', name)
def set_wrapper(info, wrapper):
if isinstance(wrapper, str):
wrapper = FunctionWrapper(wrapper)
info._Attribute('wrapper', wrapper)
def instantiate(template, types, rename=None):
if isinstance(types, str):
types = types.split()
return template.Instantiate(types, rename)
def use_shared_ptr(info):
info._Attribute('smart_ptr', 'boost::shared_ptr< %s >')
def use_auto_ptr(info):
info._Attribute('smart_ptr', 'std::auto_ptr< %s >')
def holder(info, function):
msg = "Expected a callable that accepts one string argument."
assert callable(function), msg
info._Attribute('holder', function)
def add_method(info, name, rename=None):
added = info._Attribute('__added__')
if added is None:
info._Attribute('__added__', [(name, rename)])
else:
added.append((name, rename))
def class_code(info, code):
added = info._Attribute('__code__')
if added is None:
info._Attribute('__code__', [code])
else:
added.append(code)
def final(info):
info._Attribute('no_override', True)
def export_values(info):
info._Attribute('export_values', True)

View File

@@ -1,95 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
class Policy(object):
'Represents one of the call policies of boost.python.'
def __init__(self):
if type(self) is Policy:
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 ' >'
def __eq__(self, other):
try:
return self.Code() == other.Code()
except AttributeError:
return False
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
class return_self(Policy):
def Code(self):
return 'return_self<>'
# 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'
return_opaque_pointer = 'return_opaque_pointer'
return_by_value = 'return_by_value'

View File

@@ -1,424 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
"""
Pyste version %s
Usage:
pyste [options] interface-files
where options are:
--module=<name> The name of the module that will be generated;
defaults to the first interface filename, without
the extension.
-I <path> Add an include path
-D <symbol> Define symbol
--multiple Create various cpps, instead of only one
(useful during development)
--out=<name> Specify output filename (default: <module>.cpp)
in --multiple mode, this will be a directory
--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 the empty namespace
--debug Writes the xml for each file parsed in the current
directory
--cache-dir=<dir> Directory for cache files (speeds up future runs)
--only-create-cache Recreates all caches (doesn't generate code).
--generate-main Generates the _main.cpp file (in multiple mode)
--file-list A file with one pyste file per line. Use as a
substitute for passing the files in the command
line.
--gccxml-path=<path> Path to gccxml executable (default: gccxml)
--no-default-include Do not use INCLUDE environment variable for include
files to pass along gccxml.
-h, --help Print this help and exit
-v, --version Print version information
"""
import sys
import os
import getopt
import exporters
import SingleCodeUnit
import MultipleCodeUnit
import infos
import exporterutils
import settings
import gc
import sys
from policies import *
from CppParser import CppParser, CppParserError
import time
import declarations
__version__ = '0.9.30'
def RecursiveIncludes(include):
'Return a list containg the include dir and all its subdirectories'
dirs = [include]
def visit(arg, dir, names):
# ignore CVS dirs
if os.path.split(dir)[1] != 'CVS':
dirs.append(dir)
os.path.walk(include, visit, None)
return dirs
def GetDefaultIncludes():
if 'INCLUDE' in os.environ:
include = os.environ['INCLUDE']
return include.split(os.pathsep)
else:
return []
def ProcessIncludes(includes):
if sys.platform == 'win32':
index = 0
for include in includes:
includes[index] = include.replace('\\', '/')
index += 1
def ReadFileList(filename):
f = file(filename)
files = []
try:
for line in f:
line = line.strip()
if line:
files.append(line)
finally:
f.close()
return files
def ParseArguments():
def Usage():
print __doc__ % __version__
sys.exit(1)
try:
options, files = getopt.getopt(
sys.argv[1:],
'R:I:D:vh',
['module=', 'multiple', 'out=', 'no-using', 'pyste-ns=', 'debug', 'cache-dir=',
'only-create-cache', 'version', 'generate-main', 'file-list=', 'help',
'gccxml-path=', 'no-default-include'])
except getopt.GetoptError, e:
print
print 'ERROR:', e
Usage()
default_includes = GetDefaultIncludes()
includes = []
defines = []
module = None
out = None
multiple = False
cache_dir = None
create_cache = False
generate_main = False
gccxml_path = 'gccxml'
for opt, value in options:
if opt == '-I':
includes.append(value)
elif opt == '-D':
defines.append(value)
elif opt == '-R':
includes.extend(RecursiveIncludes(value))
elif opt == '--module':
module = value
elif opt == '--out':
out = value
elif opt == '--no-using':
settings.namespaces.python = 'boost::python::'
settings.USING_BOOST_NS = False
elif opt == '--pyste-ns':
settings.namespaces.pyste = value + '::'
elif opt == '--debug':
settings.DEBUG = True
elif opt == '--multiple':
multiple = True
elif opt == '--cache-dir':
cache_dir = value
elif opt == '--only-create-cache':
create_cache = True
elif opt == '--file-list':
files += ReadFileList(value)
elif opt in ['-h', '--help']:
Usage()
elif opt in ['-v', '--version']:
print 'Pyste version %s' % __version__
sys.exit(2)
elif opt == '--generate-main':
generate_main = True
elif opt == '--gccxml-path':
gccxml_path = value
elif opt == '--no-default-include':
default_includes = []
else:
print 'Unknown option:', opt
Usage()
includes[0:0] = default_includes
if not files:
Usage()
if not module:
module = os.path.splitext(os.path.basename(files[0]))[0]
if not out:
out = module
if not multiple:
out += '.cpp'
for file in files:
d = os.path.dirname(os.path.abspath(file))
if d not in sys.path:
sys.path.append(d)
if create_cache and not cache_dir:
print 'Error: Use --cache-dir to indicate where to create the cache files!'
Usage()
sys.exit(3)
if generate_main and not multiple:
print 'Error: --generate-main only valid in multiple mode.'
Usage()
sys.exit(3)
ProcessIncludes(includes)
return includes, defines, module, out, files, multiple, cache_dir, create_cache, \
generate_main, gccxml_path
def PCHInclude(*headers):
code = '\n'.join(['#include <%s>' % x for x in headers])
infos.CodeInfo(code, 'pchinclude')
def CreateContext():
'create the context where a interface file will be executed'
context = {}
context['Import'] = Import
# infos
context['Function'] = infos.FunctionInfo
context['Class'] = infos.ClassInfo
context['Include'] = lambda header: infos.CodeInfo('#include <%s>\n' % header, 'include')
context['PCHInclude'] = PCHInclude
context['Template'] = infos.ClassTemplateInfo
context['Enum'] = infos.EnumInfo
context['AllFromHeader'] = infos.HeaderInfo
context['Var'] = infos.VarInfo
# functions
context['rename'] = infos.rename
context['set_policy'] = infos.set_policy
context['exclude'] = infos.exclude
context['set_wrapper'] = infos.set_wrapper
context['use_shared_ptr'] = infos.use_shared_ptr
context['use_auto_ptr'] = infos.use_auto_ptr
context['holder'] = infos.holder
context['add_method'] = infos.add_method
context['final'] = infos.final
context['export_values'] = infos.export_values
# 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['return_opaque_pointer'] = return_opaque_pointer
context['manage_new_object'] = manage_new_object
context['return_by_value'] = return_by_value
context['return_self'] = return_self
# utils
context['Wrapper'] = exporterutils.FunctionWrapper
context['declaration_code'] = lambda code: infos.CodeInfo(code, 'declaration-outside')
context['module_code'] = lambda code: infos.CodeInfo(code, 'module')
context['class_code'] = infos.class_code
return context
def Begin():
# parse arguments
includes, defines, module, out, interfaces, multiple, cache_dir, create_cache, generate_main, gccxml_path = ParseArguments()
# run pyste scripts
for interface in interfaces:
ExecuteInterface(interface)
# create the parser
parser = CppParser(includes, defines, cache_dir, declarations.version, gccxml_path)
try:
if not create_cache:
if not generate_main:
return GenerateCode(parser, module, out, interfaces, multiple)
else:
return GenerateMain(module, out, OrderInterfaces(interfaces))
else:
return CreateCaches(parser)
finally:
parser.Close()
def CreateCaches(parser):
# There is one cache file per interface so we organize the headers
# by interfaces. For each interface collect the tails from the
# exporters sharing the same header.
tails = JoinTails(exporters.exporters)
# now for each interface file take each header, and using the tail
# get the declarations and cache them.
for interface, header in tails:
tail = tails[(interface, header)]
declarations = parser.ParseWithGCCXML(header, tail)
cachefile = parser.CreateCache(header, interface, tail, declarations)
print 'Cached', cachefile
return 0
_imported_count = {} # interface => count
def ExecuteInterface(interface):
old_interface = exporters.current_interface
if not os.path.exists(interface):
if old_interface and os.path.exists(old_interface):
d = os.path.dirname(old_interface)
interface = os.path.join(d, interface)
if not os.path.exists(interface):
raise IOError, "Cannot find interface file %s."%interface
_imported_count[interface] = _imported_count.get(interface, 0) + 1
exporters.current_interface = interface
context = CreateContext()
context['INTERFACE_FILE'] = os.path.abspath(interface)
execfile(interface, context)
exporters.current_interface = old_interface
def Import(interface):
exporters.importing = True
ExecuteInterface(interface)
exporters.importing = False
def JoinTails(exports):
'''Returns a dict of {(interface, header): tail}, where tail is the
joining of all tails of all exports for the header.
'''
tails = {}
for export in exports:
interface = export.interface_file
header = export.Header()
tail = export.Tail() or ''
if (interface, header) in tails:
all_tails = tails[(interface,header)]
all_tails += '\n' + tail
tails[(interface, header)] = all_tails
else:
tails[(interface, header)] = tail
return tails
def OrderInterfaces(interfaces):
interfaces_order = [(_imported_count[x], x) for x in interfaces]
interfaces_order.sort()
interfaces_order.reverse()
return [x for _, x in interfaces_order]
def GenerateMain(module, out, interfaces):
codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
codeunit.GenerateMain(interfaces)
return 0
def GenerateCode(parser, module, out, interfaces, multiple):
# prepare to generate the wrapper code
if multiple:
codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
else:
codeunit = SingleCodeUnit.SingleCodeUnit(module, out)
# stop referencing the exporters here
exports = exporters.exporters
exporters.exporters = None
exported_names = dict([(x.Name(), None) for x in exports])
# order the exports
order = {}
for export in exports:
if export.interface_file in order:
order[export.interface_file].append(export)
else:
order[export.interface_file] = [export]
exports = []
interfaces_order = OrderInterfaces(interfaces)
for interface in interfaces_order:
exports.extend(order[interface])
del order
del interfaces_order
# now generate the code in the correct order
#print exported_names
tails = JoinTails(exports)
for i in xrange(len(exports)):
export = exports[i]
interface = export.interface_file
header = export.Header()
if header:
tail = tails[(interface, header)]
declarations, parsed_header = parser.Parse(header, interface, tail)
else:
declarations = []
parsed_header = None
ExpandTypedefs(declarations, exported_names)
export.SetDeclarations(declarations)
export.SetParsedHeader(parsed_header)
if multiple:
codeunit.SetCurrent(export.interface_file, export.Name())
export.GenerateCode(codeunit, exported_names)
# force collect of cyclic references
exports[i] = None
del declarations
del export
gc.collect()
# finally save the code unit
codeunit.Save()
if not multiple:
print 'Module %s generated' % module
return 0
def ExpandTypedefs(decls, exported_names):
'''Check if the names in exported_names are a typedef, and add the real class
name in the dict.
'''
for name in exported_names.keys():
for decl in decls:
if isinstance(decl, declarations.Typedef):
exported_names[decl.type.FullName()] = None
def UsePsyco():
'Tries to use psyco if possible'
try:
import psyco
psyco.profile()
except: pass
def main():
start = time.clock()
UsePsyco()
status = Begin()
print '%0.2f seconds' % (time.clock()-start)
sys.exit(status)
if __name__ == '__main__':
main()

View File

@@ -1,21 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#==============================================================================
# Global information
#==============================================================================
DEBUG = False
USING_BOOST_NS = True
class namespaces:
boost = 'boost::'
pyste = ''
python = '' # default is to not use boost::python namespace explicitly, so
# use the "using namespace" statement instead
import sys
msvc = sys.platform == 'win32'

View File

@@ -1,78 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from __future__ import generators
import string
import sys
#==============================================================================
# enumerate
#==============================================================================
def enumerate(seq):
i = 0
for x in seq:
yield i, x
i += 1
#==============================================================================
# makeid
#==============================================================================
_valid_chars = string.ascii_letters + string.digits + '_'
_valid_chars = dict(zip(_valid_chars, _valid_chars))
def makeid(name):
'Returns the name as a valid identifier'
if type(name) != str:
print type(name), name
newname = []
for char in name:
if char not in _valid_chars:
char = '_'
newname.append(char)
newname = ''.join(newname)
# avoid duplications of '_' chars
names = [x for x in newname.split('_') if x]
return '_'.join(names)
#==============================================================================
# remove_duplicated_lines
#==============================================================================
def remove_duplicated_lines(text):
includes = text.splitlines()
d = dict([(include, 0) for include in includes])
includes = d.keys()
includes.sort()
return '\n'.join(includes)
#==============================================================================
# left_equals
#==============================================================================
def left_equals(s):
s = '// %s ' % s
return s + ('='*(80-len(s))) + '\n'
#==============================================================================
# post_mortem
#==============================================================================
def post_mortem():
def info(type, value, tb):
if hasattr(sys, 'ps1') or not sys.stderr.isatty():
# we are in interactive mode or we don't have a tty-like
# device, so we call the default hook
sys.__excepthook__(type, value, tb)
else:
import traceback, pdb
# we are NOT in interactive mode, print the exception...
traceback.print_exception(type, value, tb)
print
# ...then start the debugger in post-mortem mode.
pdb.pm()
sys.excepthook = info

View File

@@ -1,341 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import sys
sys.path.append('../src')
import unittest
import tempfile
import os.path
from Pyste import GCCXMLParser
from Pyste.declarations import *
class Tester(unittest.TestCase):
def TestConstructor(self, class_, method, visib):
self.assert_(isinstance(method, Constructor))
self.assertEqual(method.FullName(), class_.FullName() + '::' + method.name)
self.assertEqual(method.result, None)
self.assertEqual(method.visibility, visib)
self.assert_(not method.virtual)
self.assert_(not method.abstract)
self.assert_(not method.static)
def TestDefaultConstructor(self, class_, method, visib):
self.TestConstructor(class_, method, visib)
self.assert_(method.IsDefault())
def TestCopyConstructor(self, class_, method, visib):
self.TestConstructor(class_, method, visib)
self.assertEqual(len(method.parameters), 1)
param = method.parameters[0]
self.TestType(
param,
ReferenceType,
class_.FullName(),
'const %s&' % class_.FullName(),
True)
self.assert_(method.IsCopy())
def TestType(self, type_, classtype_, name, fullname, const):
self.assert_(isinstance(type_, classtype_))
self.assertEqual(type_.name, name)
self.assertEqual(type_.namespace, None)
self.assertEqual(type_.FullName(), fullname)
self.assertEqual(type_.const, const)
class ClassBaseTest(Tester):
def setUp(self):
self.base = GetDecl('Base')
def testClass(self):
'test the properties of the class Base'
self.assert_(isinstance(self.base, Class))
self.assert_(self.base.abstract)
def testFoo(self):
'test function foo in class Base'
foo = GetMember(self.base, 'foo')
self.assert_(isinstance(foo, Method))
self.assertEqual(foo.visibility, Scope.public)
self.assert_(foo.virtual)
self.assert_(foo.abstract)
self.failIf(foo.static)
self.assertEqual(foo.class_, 'test::Base')
self.failIf(foo.const)
self.assertEqual(foo.FullName(), 'test::Base::foo')
self.assertEqual(foo.result.name, 'void')
self.assertEqual(len(foo.parameters), 1)
param = foo.parameters[0]
self.TestType(param, FundamentalType, 'int', 'int', False)
self.assertEqual(foo.namespace, None)
self.assertEqual(
foo.PointerDeclaration(1), '(void (test::Base::*)(int) )&test::Base::foo')
def testX(self):
'test the member x in class Base'
x = GetMember(self.base, 'x')
self.assertEqual(x.class_, 'test::Base')
self.assertEqual(x.FullName(), 'test::Base::x')
self.assertEqual(x.namespace, None)
self.assertEqual(x.visibility, Scope.private)
self.TestType(x.type, FundamentalType, 'int', 'int', False)
self.assertEqual(x.static, False)
def testConstructors(self):
'test constructors in class Base'
constructors = GetMembers(self.base, 'Base')
for cons in constructors:
if len(cons.parameters) == 0:
self.TestDefaultConstructor(self.base, cons, Scope.public)
elif len(cons.parameters) == 1: # copy constructor
self.TestCopyConstructor(self.base, cons, Scope.public)
elif len(cons.parameters) == 2: # other constructor
intp, floatp = cons.parameters
self.TestType(intp, FundamentalType, 'int', 'int', False)
self.TestType(floatp, FundamentalType, 'float', 'float', False)
def testSimple(self):
'test function simple in class Base'
simple = GetMember(self.base, 'simple')
self.assert_(isinstance(simple, Method))
self.assertEqual(simple.visibility, Scope.protected)
self.assertEqual(simple.FullName(), 'test::Base::simple')
self.assertEqual(len(simple.parameters), 1)
param = simple.parameters[0]
self.TestType(param, ReferenceType, 'std::string', 'const std::string&', True)
self.TestType(simple.result, FundamentalType, 'bool', 'bool', False)
self.assertEqual(
simple.PointerDeclaration(1),
'(bool (test::Base::*)(const std::string&) )&test::Base::simple')
def testZ(self):
z = GetMember(self.base, 'z')
self.assert_(isinstance(z, Variable))
self.assertEqual(z.visibility, Scope.public)
self.assertEqual(z.FullName(), 'test::Base::z')
self.assertEqual(z.type.name, 'int')
self.assertEqual(z.type.const, False)
self.assert_(z.static)
class ClassTemplateTest(Tester):
def setUp(self):
self.template = GetDecl('Template<int>')
def testClass(self):
'test the properties of the Template<int> class'
self.assert_(isinstance(self.template, Class))
self.assert_(not self.template.abstract)
self.assertEqual(self.template.FullName(), 'Template<int>')
self.assertEqual(self.template.namespace, '')
self.assertEqual(self.template.name, 'Template<int>')
def testConstructors(self):
'test the automatic constructors of the class Template<int>'
constructors = GetMembers(self.template, 'Template')
for cons in constructors:
if len(cons.parameters) == 0:
self.TestDefaultConstructor(self.template, cons, Scope.public)
elif len(cons.parameters) == 1:
self.TestCopyConstructor(self.template, cons, Scope.public)
def testValue(self):
'test the class variable value'
value = GetMember(self.template, 'value')
self.assert_(isinstance(value, ClassVariable))
self.assert_(value.name, 'value')
self.TestType(value.type, FundamentalType, 'int', 'int', False)
self.assert_(not value.static)
self.assertEqual(value.visibility, Scope.public)
self.assertEqual(value.class_, 'Template<int>')
self.assertEqual(value.FullName(), 'Template<int>::value')
def testBase(self):
'test the superclasses of Template<int>'
bases = self.template.bases
self.assertEqual(len(bases), 1)
base = bases[0]
self.assert_(isinstance(base, Base))
self.assertEqual(base.name, 'test::Base')
self.assertEqual(base.visibility, Scope.protected)
class FreeFuncTest(Tester):
def setUp(self):
self.func = GetDecl('FreeFunc')
def testFunc(self):
'test attributes of FreeFunc'
self.assert_(isinstance(self.func, Function))
self.assertEqual(self.func.name, 'FreeFunc')
self.assertEqual(self.func.FullName(), 'test::FreeFunc')
self.assertEqual(self.func.namespace, 'test')
self.assertEqual(
self.func.PointerDeclaration(1),
'(const test::Base& (*)(const std::string&, int))&test::FreeFunc')
def testResult(self):
'test the return value of FreeFunc'
res = self.func.result
self.TestType(res, ReferenceType, 'test::Base', 'const test::Base&', True)
def testParameters(self):
'test the parameters of FreeFunc'
self.assertEqual(len(self.func.parameters), 2)
strp, intp = self.func.parameters
self.TestType(strp, ReferenceType, 'std::string', 'const std::string&', True)
self.assertEqual(strp.default, None)
self.TestType(intp, FundamentalType, 'int', 'int', False)
self.assertEqual(intp.default, '10')
class testFunctionPointers(Tester):
def testMethodPointer(self):
'test declaration of a pointer-to-method'
meth = GetDecl('MethodTester')
param = meth.parameters[0]
fullname = 'void (test::Base::*)(int)'
self.TestType(param, PointerType, fullname, fullname, False)
def testFunctionPointer(self):
'test declaration of a pointer-to-function'
func = GetDecl('FunctionTester')
param = func.parameters[0]
fullname = 'void (*)(int)'
self.TestType(param, PointerType, fullname, fullname, False)
# =============================================================================
# Support routines
# =============================================================================
cppcode = '''
namespace std {
class string;
}
namespace test {
class Base
{
public:
Base();
Base(const Base&);
Base(int, float);
virtual void foo(int = 0.0) = 0;
static int z;
protected:
bool simple(const std::string&);
private:
int x;
};
void MethodTester( void (Base::*)(int) );
void FunctionTester( void (*)(int) );
const Base & FreeFunc(const std::string&, int=10);
}
template <class T>
struct Template: protected test::Base
{
T value;
virtual void foo(int);
};
Template<int> __aTemplateInt;
'''
def GetXMLFile():
'''Generates an gccxml file using the code from the global cppcode.
Returns the xml's filename.'''
# write the code to a header file
tmpfile = tempfile.mktemp() + '.h'
f = file(tmpfile, 'w')
f.write(cppcode)
f.close()
# run gccxml
outfile = tmpfile + '.xml'
if os.system('gccxml "%s" "-fxml=%s"' % (tmpfile, outfile)) != 0:
raise RuntimeError, 'Error executing GCCXML.'
# read the output file into the xmlcode
f = file(outfile)
xmlcode = f.read()
#print xmlcode
f.close()
# remove the header
os.remove(tmpfile)
return outfile
def GetDeclarations():
'Uses the GCCXMLParser module to get the declarations.'
xmlfile = GetXMLFile()
declarations = GCCXMLParser.ParseDeclarations(xmlfile)
os.remove(xmlfile)
return declarations
# the declarations to be analysed
declarations = GetDeclarations()
def GetDecl(name):
'returns one of the top declarations given its name'
for decl in declarations:
if decl.name == name:
return decl
else:
raise RuntimeError, 'Declaration not found: %s' % name
def GetMember(class_, name):
'gets the member of the given class by its name'
res = None
multipleFound = False
for member in class_:
if member.name == name:
if res is not None:
multipleFound = True
break
res = member
if res is None or multipleFound:
raise RuntimeError, \
'No member or more than one member found in class %s: %s' \
% (class_.name, name)
return res
def GetMembers(class_, name):
'gets the members of the given class by its name'
res = []
for member in class_:
if member.name == name:
res.append(member)
if len(res) in (0, 1):
raise RuntimeError, \
'GetMembers: 0 or 1 members found in class %s: %s' \
% (class_.name, name)
return res
if __name__ == '__main__':
unittest.main()

View File

@@ -1,84 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import sys
sys.path.append('../src')
from SmartFile import *
import unittest
import tempfile
import os
import time
class SmartFileTest(unittest.TestCase):
FILENAME = tempfile.mktemp()
def setUp(self):
self._Clean()
def tearDown(self):
self._Clean()
def _Clean(self):
try:
os.remove(self.FILENAME)
except OSError: pass
def testNonExistant(self):
"Must override the file, as there's no file in the disk yet"
self.assert_(not os.path.isfile(self.FILENAME))
f = SmartFile(self.FILENAME, 'w')
f.write('Testing 123\nTesting again.')
f.close()
self.assert_(os.path.isfile(self.FILENAME))
def testOverride(self):
"Must override the file, because the contents are different"
contents = 'Contents!\nContents!'
# create the file normally first
f = file(self.FILENAME, 'w')
f.write(contents)
f.close()
file_time = os.path.getmtime(self.FILENAME)
self.assert_(os.path.isfile(self.FILENAME))
time.sleep(2)
f = SmartFile(self.FILENAME, 'w')
f.write(contents + '_')
f.close()
new_file_time = os.path.getmtime(self.FILENAME)
self.assert_(new_file_time != file_time)
def testNoOverride(self):
"Must not override the file, because the contents are the same"
contents = 'Contents!\nContents!'
# create the file normally first
f = file(self.FILENAME, 'w')
f.write(contents)
f.close()
file_time = os.path.getmtime(self.FILENAME)
self.assert_(os.path.isfile(self.FILENAME))
time.sleep(2)
f = SmartFile(self.FILENAME, 'w')
f.write(contents)
f.close()
new_file_time = os.path.getmtime(self.FILENAME)
self.assert_(new_file_time == file_time)
def testAutoClose(self):
"Must be closed when garbage-collected"
def foo():
f = SmartFile(self.FILENAME)
f.write('testing')
self.assert_(not os.path.isfile(self.FILENAME))
foo()
self.assert_(os.path.isfile(self.FILENAME))
if __name__ == '__main__':
unittest.main()

View File

@@ -1,22 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#include <vector>
#include <string>
namespace abstract {
struct A {
virtual ~A() {}
virtual std::string f()=0;
};
struct B: A {
std::string f() { return "B::f"; }
};
std::string call(A* a) { return a->f(); }
}

View File

@@ -1,3 +0,0 @@
Class('abstract::A', 'abstract_test.h')
Class('abstract::B', 'abstract_test.h')
Function('abstract::call', 'abstract_test.h')

View File

@@ -1,26 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _abstract_test import *
class AbstractTest(unittest.TestCase):
def testIt(self):
class C(A):
def f(self):
return 'C::f'
a = A()
b = B()
c = C()
self.assertRaises(RuntimeError, a.f)
self.assertEqual(b.f(), 'B::f')
self.assertEqual(call(b), 'B::f')
self.assertEqual(c.f(), 'C::f')
self.assertEqual(call(c), 'C::f')
if __name__ == '__main__':
unittest.main()

View File

@@ -1,18 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
namespace add_test {
struct C
{
int x;
};
const int get_x(C& c)
{
return c.x;
}
}

View File

@@ -1,2 +0,0 @@
C = Class('add_test::C', 'add_test.h')
add_method(C, 'add_test::get_x')

View File

@@ -1,16 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _add_test import *
class AddMethodTest(unittest.TestCase):
def testIt(self):
c = C()
c.x = 10
self.assertEqual(c.get_x(), 10)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,13 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#include "basic.h"
namespace basic {
int C::static_value = 3;
const int C::const_static_value = 100;
}

View File

@@ -1,69 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BASIC_H
#define BASIC_H
#include <string>
namespace basic {
struct C
{
// test virtuallity
C(): value(1), const_value(0) {}
virtual int f(int x = 10)
{
return x*2;
}
int foo(int x=1){
return x+1;
}
const std::string& get_name() { return name; }
void set_name(const std::string& name) { this->name = name; }
private:
std::string name;
public:
// test data members
static int static_value;
static const int const_static_value;
int value;
const int const_value;
// test static functions
static int mul(int x, int y) { return x*y; }
static double mul(double x, double y) { return x*y; }
static int square(int x=2) { return x*x; }
};
inline int call_f(C& c)
{
return c.f();
}
inline int call_f(C& c, int x)
{
return c.f(x);
}
inline int get_static()
{
return C::static_value;
}
inline int get_value(C& c)
{
return c.value;
}
}
#endif

View File

@@ -1,5 +0,0 @@
Class('basic::C', 'basic.h')
Function('basic::call_f', 'basic.h')
Function('basic::get_static', 'basic.h')
Function('basic::get_value', 'basic.h')

View File

@@ -1,73 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _basic import *
class BasicExampleTest(unittest.TestCase):
def testIt(self):
# test virtual functions
class D(C):
def f(self, x=10):
return x+1
d = D()
c = C()
self.assertEqual(c.f(), 20)
self.assertEqual(c.f(3), 6)
self.assertEqual(d.f(), 11)
self.assertEqual(d.f(3), 4)
self.assertEqual(call_f(c), 20)
self.assertEqual(call_f(c, 4), 8)
self.assertEqual(call_f(d), 11)
self.assertEqual(call_f(d, 3), 4)
# test data members
def testValue(value):
self.assertEqual(c.value, value)
self.assertEqual(d.value, value)
self.assertEqual(get_value(c), value)
self.assertEqual(get_value(d), value)
testValue(1)
c.value = 30
d.value = 30
testValue(30)
self.assertEqual(c.const_value, 0)
self.assertEqual(d.const_value, 0)
def set_const_value():
c.const_value = 12
self.assertRaises(AttributeError, set_const_value)
# test static data-members
def testStatic(value):
self.assertEqual(C.static_value, value)
self.assertEqual(c.static_value, value)
self.assertEqual(D.static_value, value)
self.assertEqual(d.static_value, value)
self.assertEqual(get_static(), value)
testStatic(3)
C.static_value = 10
testStatic(10)
self.assertEqual(C.const_static_value, 100)
def set_const_static():
C.const_static_value = 1
self.assertRaises(AttributeError, set_const_static)
# test static function
def test_mul(result, *args):
self.assertEqual(C.mul(*args), result)
self.assertEqual(c.mul(*args), result)
test_mul(16, 8, 2)
test_mul(6.0, 2.0, 3.0)
self.assertEqual(C.square(), 4)
self.assertEqual(c.square(), 4)
self.assertEqual(C.square(3), 9)
self.assertEqual(c.square(3), 9)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,8 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
struct A {
int x;
};

View File

@@ -1,9 +0,0 @@
Class('A', 'code_test.h')
Include('string')
declaration_code('''
int get(A& a) { return a.x; }
std::string foo() { return "Hello!"; }
''')
module_code(' def("get", &get);\n')
module_code(' def("foo", &foo);\n')

View File

@@ -1,18 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _code_test import *
class CodeTest(unittest.TestCase):
def testIt(self):
a = A()
a.x = 12
self.assertEqual(get(a), 12)
self.assertEqual(foo(), "Hello!")
if __name__ == '__main__':
unittest.main()

View File

@@ -1,34 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef ENUMS_H
#define ENUMS_H
namespace enums {
enum color { red, blue };
struct X
{
enum choices
{
good = 1,
bad = 2
};
int set(choices c)
{
return (int)c;
}
};
enum {
x = 0,
y = 1
};
}
#endif

View File

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

View File

@@ -1,24 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _enums import *
class EnumsTest(unittest.TestCase):
def testIt(self):
self.assertEqual(int(Red), 0)
self.assertEqual(int(Blue), 1)
self.assertEqual(int(X.Choices.Good), 1)
self.assertEqual(int(X.Choices.Bad), 2)
a = X()
self.assertEqual(a.set(a.Choices.Good), 1)
self.assertEqual(a.set(a.Choices.Bad), 2)
self.assertEqual(x, 0)
self.assertEqual(y, 1)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,43 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef HEADER_TEST_H
#define HEADER_TEST_H
#include <map>
#include <string>
namespace header_test {
enum choice { red, blue };
inline std::string choice_str(choice c)
{
std::map<choice, std::string> choice_map;
choice_map[red] = "red";
choice_map[blue] = "blue";
return choice_map[c];
}
struct C
{
choice c;
std::string get()
{
return choice_str(c);
}
};
// test the exclusion of the following
struct ForwardDeclared; // should be excluded automatically
struct A {};
void foo();
enum bar { value };
}
#endif

View File

@@ -1,4 +0,0 @@
h = AllFromHeader('header_test.h')
exclude(h.A)
exclude(h.foo)
exclude(h.bar)

View File

@@ -1,27 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _header_test import *
class HeaderTest(unittest.TestCase):
def testIt(self):
self.assertEqual(choice.red, 0)
self.assertEqual(choice.blue, 1)
self.assertEqual(choice_str(choice.blue), 'blue')
self.assertEqual(choice_str(choice.red), 'red')
c = C()
c.c = choice.blue
self.assertEqual(c.get(), 'blue')
c.c = choice.red
self.assertEqual(c.get(), 'red')
# the following classes/functions should not have being exported
self.assertRaises(NameError, lambda: A())
self.assertRaises(NameError, lambda: foo())
self.assertRaises(NameError, lambda: bar.value)
self.assertRaises(NameError, lambda: ForwardDeclared())
if __name__ == '__main__':
unittest.main()

View File

@@ -1,55 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import sys
from Pyste.infos import *
from Pyste.policies import *
from Pyste.exporterutils import *
import unittest
#================================================================================
# InfosTest
#================================================================================
class InfosTest(unittest.TestCase):
def testFunctionInfo(self):
info = FunctionInfo('test::foo', 'foo.h')
rename(info, 'hello')
set_policy(info, return_internal_reference())
set_wrapper(info, FunctionWrapper('foo_wrapper'))
info = InfoWrapper(info)
self.assertEqual(info.rename, 'hello')
self.assertEqual(info.policy.Code(), 'return_internal_reference< 1 >')
self.assertEqual(info.wrapper.name, 'foo_wrapper')
def testClassInfo(self):
info = ClassInfo('test::IFoo', 'foo.h')
rename(info.name, 'Name')
rename(info.exclude, 'Exclude')
rename(info, 'Foo')
rename(info.Bar, 'bar')
set_policy(info.Baz, return_internal_reference())
rename(info.operator['>>'], 'from_string')
exclude(info.Bar)
set_wrapper(info.Baz, FunctionWrapper('baz_wrapper'))
info = InfoWrapper(info)
self.assertEqual(info.rename, 'Foo')
self.assertEqual(info['Bar'].rename, 'bar')
self.assertEqual(info['name'].rename, 'Name')
self.assertEqual(info['exclude'].rename, 'Exclude')
self.assertEqual(info['Bar'].exclude, True)
self.assertEqual(info['Baz'].policy.Code(), 'return_internal_reference< 1 >')
self.assertEqual(info['Baz'].wrapper.name, 'baz_wrapper')
self.assertEqual(info['operator']['>>'].rename, 'from_string')
if __name__ == '__main__':
unittest.main()

View File

@@ -1,8 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#include "inherit.h"
int inherit::C::s = 1;

View File

@@ -1,43 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
namespace inherit {
template<typename T>
class A
{
public:
void set(T v) { mData = v; }
T get() const { return mData; }
private:
T mData;
};
class B : public A<int>
{
public:
int go() { return get(); }
};
struct C : B
{
enum ab { a = 1, b = 2 };
int f1() { return 1; }
int x;
static int s;
};
struct D : C
{
int f2() { return 2; }
int y;
};
struct X {};
struct E: X, D {};
}

View File

@@ -1,8 +0,0 @@
A = Template('inherit::A', 'inherit.h')
A_int = A('int', 'A_int')
Class('inherit::B', 'inherit.h')
Class('inherit::D', 'inherit.h')
E = Class('inherit::E', 'inherit.h')
exclude(E.s)
exclude(E.ab)

View File

@@ -1,35 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
namespace inherit2 {
struct A
{
int x;
int getx() { return x; }
int foo() { return 0; }
int foo(int x) { return x; }
};
struct B : A
{
int y;
int gety() { return y; }
int foo() { return 1; }
};
struct C : B
{
int z;
int getz() { return z; }
};
struct D : C
{
int w;
int getw() { return w; }
};
}

View File

@@ -1,2 +0,0 @@
Class('inherit2::B', 'inherit2.h')
Class('inherit2::D', 'inherit2.h')

View File

@@ -1,31 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _inherit2 import *
class InheritExampleTest(unittest.TestCase):
def testIt(self):
b = B()
d = D()
self.assert_(issubclass(D, B))
b.x, b.y = 10, 5
self.assertEqual(b.getx(), 10)
self.assertEqual(b.gety(), 5)
d.x, d.y, d.z, d.w = 20, 15, 10, 5
self.assertEqual(d.getx(), 20)
self.assertEqual(d.gety(), 15)
self.assertEqual(d.getz(), 10)
self.assertEqual(d.getw(), 5)
self.assertEqual(b.foo(), 1)
self.assertEqual(b.foo(3), 3)
def wrong():
return b.getw()
self.assertRaises(AttributeError, wrong)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,46 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
namespace inherit3 {
struct A
{
A() { x = 0; }
struct X { int y; };
int x;
virtual int foo() { return 0; }
virtual int foo(int x) { return x; }
A operator+(A o) const
{
A r;
r.x = o.x + x;
return r;
}
enum E { i, j };
};
struct B: A
{
B() { x = 0; }
struct X { int y; };
int x;
int foo() { return 1; }
A operator+(A o) const
{
A r;
r.x = o.x + x;
return r;
}
enum E { i, j };
};
struct C: A
{
};
}

View File

@@ -1,2 +0,0 @@
Class('inherit3::B', 'inherit3.h')
Class('inherit3::C', 'inherit3.h')

View File

@@ -1,27 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _inherit3 import *
class testInherit3(unittest.TestCase):
def testIt(self):
def testInst(c):
self.assertEqual(c.x, 0)
self.assertEqual(c.foo(3), 3)
x = c.X()
self.assertEqual(x.y, 0)
self.assertEqual(c.E.i, 0)
self.assertEqual(c.E.j, 1)
b = B()
c = C()
testInst(b)
testInst(c)
self.assertEqual(b.foo(), 1)
self.assertEqual(c.foo(), 0)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,23 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
namespace inherit4 {
struct A
{
int x;
};
struct B: A
{
int y;
};
struct C: B
{
int z;
};
}

View File

@@ -1,3 +0,0 @@
Class('inherit4::A', 'inherit4.h')
Class('inherit4::B', 'inherit4.h')
Class('inherit4::C', 'inherit4.h')

View File

@@ -1,31 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _inherit4 import *
class TestInherit4(unittest.TestCase):
def testIt(self):
self.assert_(issubclass(B, A))
self.assert_(issubclass(C, A))
self.assert_(issubclass(C, B))
a = A()
a.x = 1
b = B()
b.x = 10
b.y = 20
c = C()
c.x = 100
c.y = 200
c.z = 300
self.assertEqual(a.x, 1)
self.assertEqual(b.x, 10)
self.assertEqual(b.y, 20)
self.assertEqual(c.x, 100)
self.assertEqual(c.y, 200)
self.assertEqual(c.z, 300)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,33 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _inherit import *
class InheritExampleTest(unittest.TestCase):
def testIt(self):
a = A_int()
b = B()
self.assert_(isinstance(b, A_int))
self.assert_(issubclass(B, A_int))
a.set(10)
self.assertEqual(a.get(), 10)
b.set(1)
self.assertEqual(b.go(), 1)
self.assertEqual(b.get(), 1)
d = D()
self.assert_(issubclass(D, B))
self.assertEqual(d.x, 0)
self.assertEqual(d.y, 0)
self.assertEqual(d.s, 1)
self.assertEqual(D.s, 1)
self.assertEqual(d.f1(), 1)
self.assertEqual(d.f2(), 2)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,9 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#include "nested.h"
int nested::X::staticXValue = 10;
int nested::X::Y::staticYValue = 20;

View File

@@ -1,32 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef NESTED_H
#define NESTED_H
namespace nested {
struct X
{
struct Y
{
int valueY;
static int staticYValue;
struct Z
{
int valueZ;
};
};
static int staticXValue;
int valueX;
};
typedef X Root;
}
#endif

View File

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

View File

@@ -1,19 +0,0 @@
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import unittest
from _nested import *
class NestedTest(unittest.TestCase):
def testIt(self):
self.assertEqual(Root.staticXValue, 10)
self.assertEqual(Root.Y.staticYValue, 20)
z = Root.Y.Z()
z.valueZ = 3
self.assertEqual(z.valueZ, 3)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,57 +0,0 @@
/* Copyright Bruno da Silva de Oliveira 2003. Use, modification and
distribution is subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OPAQUE_H
#define OPAQUE_H
#include <iostream>
namespace opaque {
struct C {
C(int v): value(v) {}
int value;
};
inline C* new_C()
{
return new C(10);
}
inline C* new_C_zero()
{
return new C(0);
}
inline int get(C* c)
{
return c->value;
}
struct D {
D(double v): value(v) {}
double value;
};
struct A
{
D* new_handle()
{
return new D(3.0);
}
double get(D* d)
{
return d->value;
}
int f(int x=0) { return x; }
};
}
#endif

View File

@@ -1,7 +0,0 @@
foo = Function('opaque::new_C', 'opaque.h')
set_policy(foo, return_value_policy(return_opaque_pointer))
foo = Function('opaque::new_C_zero', 'opaque.h')
set_policy(foo, return_value_policy(return_opaque_pointer))
Function('opaque::get', 'opaque.h' )
A = Class('opaque::A', 'opaque.h')
set_policy(A.new_handle, return_value_policy(return_opaque_pointer))

Some files were not shown because too many files have changed in this diff Show More