diff --git a/pyste/example/virtual.h b/pyste/example/virtual.h index 32ef3ebf..cd194315 100644 --- a/pyste/example/virtual.h +++ b/pyste/example/virtual.h @@ -8,6 +8,9 @@ public: return f_abs(); } + virtual void bar(int) {} + virtual void bar(char*) {} + const char* get_name() { return name(); @@ -16,7 +19,7 @@ public: protected: virtual int f_abs() = 0; -private: +private: virtual const char* name() { return "C"; } }; diff --git a/pyste/src/ClassExporter.py b/pyste/src/ClassExporter.py index dadbdc00..e36c9dda 100644 --- a/pyste/src/ClassExporter.py +++ b/pyste/src/ClassExporter.py @@ -622,6 +622,7 @@ class _VirtualWrapperGenerator(object): self.info = info self.wrapper_name = makeid(class_.FullName()) + '_Wrapper' self.virtual_methods = None + self._method_count = {} self.GenerateVirtualMethods() @@ -666,7 +667,6 @@ class _VirtualWrapperGenerator(object): decl += indent + '}\n' # default implementations (with overloading) - # only for classes that are not abstract, and public methods def DefaultImpl(method, param_names): 'Return the body of a default implementation wrapper' wrapper = self.info[method.name].wrapper @@ -679,7 +679,7 @@ class _VirtualWrapperGenerator(object): params = ', '.join(['this'] + param_names) return '%s%s(%s);\n' % (return_str, wrapper.FullName(), params) - if not method.abstract and method.visibility == Scope.public: + if not method.abstract and method.visibility != Scope.private: minArgs = method.minArgs maxArgs = method.maxArgs impl_names = self.DefaultImplementationNames(method) @@ -747,27 +747,45 @@ class _VirtualWrapperGenerator(object): This method creates the instance variable self.virtual_methods. ''' def IsVirtual(m): - return type(m) == Method and m.virtual + return m.virtual and m.visibility != Scope.private all_members = self.class_.members[:] for base in self.bases: for base_member in base.members: base_member.class_ = self.class_.FullName() all_members.append(base_member) - # extract the virtual methods, avoiding duplications + + # extract the virtual methods, avoiding duplications. The duplication + # must take in account the full signature without the class name, so + # that inherited members are correctly excluded if the subclass overrides + # them. + def MethodSig(method): + if method.const: + const = 'const' + else: + const = '' + if method.result: + result = method.result.FullName() + else: + result = '' + params = ', '.join([x.FullName() for x in method.parameters]) + return '%s %s(%s) %s' % (result, method.name, params, const) + + all_members = [x for x in all_members if type(x) == Method] self.virtual_methods = [] already_added = {} for member in all_members: - if IsVirtual(member) and not member.FullName() in already_added: + sig = MethodSig(member) + if IsVirtual(member) and not sig in already_added: self.virtual_methods.append(member) - already_added[member.FullName()] = 0 + already_added[sig] = 0 def IsMethodUnique(self, method): - count = {} - for m in self.virtual_methods: - count[m.name] = count.get(m.name, 0) + 1 - return count[m.name] == 1 + if not self._method_count: + for m in self.virtual_methods: + self._method_count[m.name] = self._method_count.get(m.name, 0) + 1 + return self._method_count[method] == 1 def Constructors(self): diff --git a/pyste/src/GCCXMLParser.py b/pyste/src/GCCXMLParser.py index 7248ee6f..dd752c22 100644 --- a/pyste/src/GCCXMLParser.py +++ b/pyste/src/GCCXMLParser.py @@ -87,24 +87,29 @@ class GCCXMLParser(object): 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] + def Check(id, feature): + pos = id.find(feature) + if pos != -1: + id = id[:pos] + id[pos+1:] + return True, id + else: + return False, id + const, id = Check(id, 'c') + volatile, id = Check(id, 'v') + restricted, id = Check(id, 'r') decl = self.GetDecl(id) if isinstance(decl, Type): res = deepcopy(decl) if const: res.const = const - if volatile: + if volatile: res.volatile = volatile + if restricted: + res.restricted = restricted else: res = Type(decl.FullName(), const) res.volatile = volatile + res.restricted = restricted res.incomplete = decl.incomplete return res @@ -404,3 +409,7 @@ def ParseDeclarations(filename): parser = GCCXMLParser() parser.Parse(filename) return parser.Declarations() + + +if __name__ == '__main__': + ParseDeclarations(r'D:\Programming\Libraries\boost-cvs\boost\libs\python\pyste\example\test.xml') diff --git a/pyste/src/declarations.py b/pyste/src/declarations.py index f9eb2c27..00c9ce79 100644 --- a/pyste/src/declarations.py +++ b/pyste/src/declarations.py @@ -280,6 +280,7 @@ class Type(Declaration): # used when the Type is a function argument self.default = default self.volatile = False + self.restricted = False self.incomplete = incomplete def __repr__(self): diff --git a/pyste/src/exporterutils.py b/pyste/src/exporterutils.py index 2efa1892..6dafe39a 100644 --- a/pyste/src/exporterutils.py +++ b/pyste/src/exporterutils.py @@ -47,14 +47,14 @@ def HandlePolicy(function, policy): return type.FullName() == '_object *' # internal name of PyObject result = function.result - # basic test if the result type demands a policy - needs_policy = isinstance(result, (ReferenceType, PointerType)) # if the function returns const char*, a policy is not needed if IsString(result) or IsPyObject(result): - needs_policy = False + return policy # if returns a const T&, set the default policy if policy is None and result.const and isinstance(result, ReferenceType): policy = return_value_policy(copy_const_reference) + # basic test if the result type demands a policy + needs_policy = isinstance(result, (ReferenceType, PointerType)) # show a warning to the user, if needed if needs_policy and policy is None: global _printed_warnings diff --git a/pyste/src/pyste.py b/pyste/src/pyste.py index b1e54e26..1ec994bc 100644 --- a/pyste/src/pyste.py +++ b/pyste/src/pyste.py @@ -34,7 +34,7 @@ from policies import * from CppParser import CppParser, CppParserError import time -__VERSION__ = '0.7.6' +__VERSION__ = '0.7.7' def RecursiveIncludes(include): 'Return a list containg the include dir and all its subdirectories' diff --git a/pyste/tests/example_virtual.py b/pyste/tests/example_virtual.py index 66b25c24..10adefe7 100644 --- a/pyste/tests/example_virtual.py +++ b/pyste/tests/example_virtual.py @@ -25,6 +25,14 @@ class VirtualTest(unittest.TestCase): self.assertEqual(d.get_name(), 'C') self.assertEqual(e.get_name(), 'E') + #c = C() + #def bar(arg): + # c.bar(arg) + #bar(1) # ok + #bar('a') # ok + #self.assertRaises(TypeError, bar, 1.0) + + if __name__ == '__main__':