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

Compare commits

...

1 Commits

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

[SVN r19444]
2003-08-04 17:55:29 +00:00
50 changed files with 0 additions and 3112 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,26 +0,0 @@
#include <map>
#include <string>
namespace header_test {
enum choice { red, blue };
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);
}
};
}

View File

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

View File

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

View File

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

View File

@@ -1,43 +0,0 @@
#include <iostream>
namespace operators {
struct C
{
static double x;
double value;
const C operator+(const C other) const
{
C c;
c.value = value + other.value;
return c;
}
operator int() const
{
return value;
}
double operator()()
{
return C::x;
}
double operator()(double other)
{
return C::x + other;
}
};
double C::x = 10;
const C operator*(const C& lhs, const C& rhs)
{
C c;
c.value = lhs.value * rhs.value;
return c;
}
}

View File

@@ -1 +0,0 @@
Class('operators::C', 'operators.h')

View File

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

View File

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

View File

@@ -1,16 +0,0 @@
namespace unions {
class UnionTest
{
public:
union // unions are not supported for now
{
int i;
short s1;
short s2;
} mBad;
int mGood;
};
}

View File

@@ -1,2 +0,0 @@
UnionTest = Class('unions::UnionTest', 'unions.h')
exclude(UnionTest.mBad)

View File

@@ -1,23 +0,0 @@
struct C
{
public:
virtual int f()
{
return f_abs();
}
const char* get_name()
{
return name();
}
protected:
virtual int f_abs() = 0;
private:
virtual const char* name() { return "C"; }
};
int call_f(C& c) { return c.f(); }

View File

@@ -1 +0,0 @@
Class('C', 'virtual.h')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,19 +0,0 @@
@echo off
setlocal
set MODULE_NAME=%1
set PYSTE_FILE=%2
set BOOST_ROOT=d:/programming/libraries/boost-cvs
set PYTHON_ROOT=c:/python
set STLPORT_ROOT=d:/programming/libraries/stlport-4.5.3
set PYSTE_FILE_DIR=%@PATH[%PYSTE_FILE]
python ../src/pyste.py -I%PYSTE_FILE_DIR --out=%MODULE_NAME.cpp --module=%MODULE_NAME %PYSTE_FILE
icl /nologo /LD /GR /GX -I%PYSTE_FILE_DIR -I%STLPORT_ROOT/stlport -I%BOOST_ROOT/boost -I%PYTHON_ROOT/include %MODULE_NAME.cpp /link /libpath:%PYTHON_ROOT/libs /libpath:%BOOST_ROOT/lib /libpath:%STLPORT_ROOT/lib boost_python.lib
rm %MODULE_NAME.cpp
rm %MODULE_NAME.exp
rm %MODULE_NAME.lib
rm %MODULE_NAME.obj
endlocal

View File

@@ -1,27 +0,0 @@
import unittest
import os
class BasicExampleTest(unittest.TestCase):
def testIt(self):
from basic import C, call_f
class D(C):
def f(self, x=10):
return x+1
d = D()
c = C()
self.assertEqual(c.f(), 20)
self.assertEqual(c.f(3), 6)
self.assertEqual(d.f(), 11)
self.assertEqual(d.f(3), 4)
self.assertEqual(call_f(c), 20)
self.assertEqual(call_f(c, 4), 8)
self.assertEqual(call_f(d), 11)
self.assertEqual(call_f(d, 3), 4)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,18 +0,0 @@
import unittest
from enums import *
class EnumsTest(unittest.TestCase):
def testIt(self):
self.assertEqual(int(color.Red), 0)
self.assertEqual(int(color.Blue), 1)
self.assertEqual(int(X.Choices.Good), 1)
self.assertEqual(int(X.Choices.Bad), 2)
x = X()
self.assertEqual(x.set(x.Choices.Good), 1)
self.assertEqual(x.set(x.Choices.Bad), 2)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,15 +0,0 @@
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')

View File

@@ -1,15 +0,0 @@
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,25 +0,0 @@
import unittest
from operators import *
class OperatorTest(unittest.TestCase):
def testIt(self):
c = C()
c.value = 3.0
d = C()
d.value = 2.0
self.assertEqual(c.x, 10)
self.assertEqual(C.x, 10)
self.assertEqual(C.x, 10)
self.assertEqual((c * d).value, 6.0)
self.assertEqual((c + d).value, 5.0)
self.assertEqual(int(c), 3)
self.assertEqual(int(d), 2)
self.assertEqual(c(), 10)
self.assertEqual(d(), 10)
self.assertEqual(c(3.0), 13.0)
self.assertEqual(d(6.0), 16.0)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,26 +0,0 @@
import unittest
from templates import *
class TemplatesTest(unittest.TestCase):
def testIt(self):
fp = FPoint()
fp.i = 3.0
fp.j = 4
ip = IPoint()
ip.x = 10
ip.y = 3.0
self.assertEqual(fp.i, 3.0)
self.assertEqual(fp.j, 4)
self.assertEqual(ip.x, 10)
self.assertEqual(ip.y, 3.0)
self.assertEqual(type(fp.i), float)
self.assertEqual(type(fp.j), int)
self.assertEqual(type(ip.x), int)
self.assertEqual(type(ip.y), float)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,31 +0,0 @@
import unittest
from virtual import *
class VirtualTest(unittest.TestCase):
def testIt(self):
class D(C):
def f_abs(self):
return 3
class E(C):
def f(self):
return 10
def name(self):
return 'E'
d = D()
e = E()
self.assertEqual(d.f(), 3)
self.assertEqual(call_f(d), 3)
self.assertEqual(e.f(), 10)
self.assertEqual(call_f(e), 10)
self.assertEqual(d.get_name(), 'C')
self.assertEqual(e.get_name(), 'E')
if __name__ == '__main__':
unittest.main()

View File

@@ -1,11 +0,0 @@
import unittest
from wrappertest import *
class WrapperTest(unittest.TestCase):
def testIt(self):
self.assertEqual(Range(10), range(10))
self.assertEqual(C().Mul(10), [x*10 for x in range(10)])
if __name__ == '__main__':
unittest.main()

View File

@@ -1,20 +0,0 @@
@echo off
call build_pyste_nt basic ../example/basic.pyste
call build_pyste_nt enums ../example/enums.pyste
call build_pyste_nt header_test ../example/header_test.pyste
call build_pyste_nt nested ../example/nested.pyste
call build_pyste_nt operators ../example/operators.pyste
call build_pyste_nt templates ../example/templates.pyste
call build_pyste_nt virtual ../example/virtual.pyste
call build_pyste_nt wrappertest ../example/wrappertest.pyste
call build_pyste_nt unions ../example/unions.pyste
runtests.py
if errorlevel != 0 goto end
rm *.dll
rm *.pyc
:end