diff --git a/pyste/NEWS b/pyste/NEWS index 3505706d..97ba5a86 100644 --- a/pyste/NEWS +++ b/pyste/NEWS @@ -1,3 +1,6 @@ +2 June 2003 +Added a new construct, add_method. See documentation. + 23 May 2003 Support for global variables added. Various bug fixes. @@ -7,8 +10,10 @@ 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. +- 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. diff --git a/pyste/doc/adding_new_methods.html b/pyste/doc/adding_new_methods.html new file mode 100644 index 00000000..ccaca6f7 --- /dev/null +++ b/pyste/doc/adding_new_methods.html @@ -0,0 +1,78 @@ + +
+ +
+ |
+ + Adding New Methods + | +
![]() |
+ ![]() |
+ ![]() |
+
+Suppose that you want to add a function to a class, turning it into a method:
+
+ 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 method 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 +method:
+
+ 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!
+
+![]() |
+ ![]() |
+ ![]() |
+
Copyright © 2003 Bruno da Silva de Oliveira
Copyright © 2002-2003 Joel de Guzman
+Permission to copy, use, modify, sell and distribute this document
+ is granted provided this copyright notice appears in all copies. This document
+ is provided "as is" without express or implied warranty, and with
+ no claim as to its suitability for any purpose.
![]() |
![]() |
- ![]() |
+ ![]() |
@@ -36,7 +37,7 @@ functions, and export those.




Copyright © 2003 Bruno da Silva de Oliveira
Copyright © 2002-2003 Joel de Guzman
diff --git a/pyste/src/ClassExporter.py b/pyste/src/ClassExporter.py
index 63bc26f3..bfb38cee 100644
--- a/pyste/src/ClassExporter.py
+++ b/pyste/src/ClassExporter.py
@@ -271,27 +271,41 @@ class ClassExporter(Exporter):
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'
+ '''Export all the non-virtual methods of this class, plus any function
+ that is to be exported as a method'''
- def OverloadName(m):
- 'Returns the name of the overloads struct for the given method'
- return makeid(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:
- if m.static:
- 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, OverloadName(m), func, m.minArgs, m.maxArgs)
- if code not in declared:
- declared[code] = True
- self.Add('declaration', code)
+ 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):
@@ -301,7 +315,11 @@ class ClassExporter(Exporter):
if wrapper:
return '&' + wrapper.FullName()
# return normal pointers to the methods of the class
- is_unique = self.class_.IsUnique(m.name)
+ if isinstance(m, Method):
+ is_unique = self.class_.IsUnique(m.name)
+ else:
+ # function
+ is_unique = len(self.GetDeclarations(m.FullName())) == 1
if is_unique:
return '&' + method.FullName()
else:
@@ -310,9 +328,10 @@ class ClassExporter(Exporter):
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
+ 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())
for method in methods:
method_info = self.info[method.name]
@@ -336,7 +355,7 @@ class ClassExporter(Exporter):
if method.minArgs != method.maxArgs:
# add the overloads for this method
DeclareOverloads(method)
- overload_name = OverloadName(method)
+ overload_name = self.OverloadName(method)
overload = ', %s%s()' % (namespaces.pyste, overload_name)
# build the .def string to export the method
@@ -347,7 +366,7 @@ class ClassExporter(Exporter):
code += ')'
self.Add('inside', code)
# static method
- if method.static:
+ if isinstance(method, Method) and method.static:
code = '.staticmethod("%s")' % name
self.Add('inside', code)
# add wrapper code if this method has one
@@ -593,7 +612,6 @@ class ClassExporter(Exporter):
self.Add('declaration-outside', macro)
self._exported_opaque_pointers[macro] = 1
-
#==============================================================================
# Virtual Wrapper utils
diff --git a/pyste/src/Exporter.py b/pyste/src/Exporter.py
index e98988c0..c47a05c4 100644
--- a/pyste/src/Exporter.py
+++ b/pyste/src/Exporter.py
@@ -8,10 +8,9 @@ class Exporter:
INDENT = ' ' * 4
- def __init__(self, info, parser_tail=None, parser_decl=None):
+ def __init__(self, info, parser_tail=None):
self.info = info
self.parser_tail = parser_tail
- self.parser_decl = parser_decl
def Name(self):
@@ -22,8 +21,7 @@ class Exporter:
self.parser = parser
header = self.info.include
tail = self.parser_tail
- decl = self.parser_decl
- declarations, parser_header = parser.parse(header, tail, decl)
+ declarations, parser_header = parser.parse(header, tail)
self.parser_header = parser_header
self.SetDeclarations(declarations)
diff --git a/pyste/src/infos.py b/pyste/src/infos.py
index d4534532..863d8ad4 100644
--- a/pyste/src/infos.py
+++ b/pyste/src/infos.py
@@ -184,29 +184,34 @@ class InfoWrapper:
#==============================================================================
# Functions
#==============================================================================
-def exclude(option):
- option._Attribute('exclude', True)
+def exclude(info):
+ info._Attribute('exclude', True)
-def set_policy(option, policy):
- option._Attribute('policy', policy)
+def set_policy(info, policy):
+ info._Attribute('policy', policy)
-def rename(option, name):
- option._Attribute('rename', name)
+def rename(info, name):
+ info._Attribute('rename', name)
-def set_wrapper(option, wrapper):
+def set_wrapper(info, wrapper):
if isinstance(wrapper, str):
wrapper = FunctionWrapper(wrapper)
- option._Attribute('wrapper', 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(option):
- option._Attribute('smart_ptr', 'boost::shared_ptr< %s >')
+def use_shared_ptr(info):
+ info._Attribute('smart_ptr', 'boost::shared_ptr< %s >')
-def use_auto_ptr(option):
- option._Attribute('smart_ptr', 'std::auto_ptr< %s >')
+def use_auto_ptr(info):
+ info._Attribute('smart_ptr', 'std::auto_ptr< %s >')
-
+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))
diff --git a/pyste/src/pyste.py b/pyste/src/pyste.py
index f163fea5..59d524e4 100644
--- a/pyste/src/pyste.py
+++ b/pyste/src/pyste.py
@@ -37,7 +37,7 @@ from policies import *
from CppParser import CppParser, CppParserError
import time
-__VERSION__ = '0.8.2'
+__VERSION__ = '0.9.0'
def RecursiveIncludes(include):
'Return a list containg the include dir and all its subdirectories'
@@ -136,6 +136,7 @@ def CreateContext():
context['set_wrapper'] = infos.set_wrapper
context['use_shared_ptr'] = infos.use_shared_ptr
context['use_auto_ptr'] = infos.use_auto_ptr
+ context['add_method'] = infos.add_method
# policies
context['return_internal_reference'] = return_internal_reference
context['with_custodian_and_ward'] = with_custodian_and_ward
diff --git a/pyste/tests/_smart_tr.cpp b/pyste/tests/_smart_tr.cpp
deleted file mode 100644
index f5bc2844..00000000
--- a/pyste/tests/_smart_tr.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-
-// Includes ====================================================================
-#include