[pygccxml-commit] SF.net SVN: pygccxml:[1507] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2008-12-27 10:57:42
|
Revision: 1507 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1507&view=rev Author: roman_yakovenko Date: 2008-12-27 10:57:29 +0000 (Sat, 27 Dec 2008) Log Message: ----------- first code creators classes for ctypes Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/class_declaration.py pygccxml_dev/unittests/data/core_cache.hpp pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/code_creator.py pyplusplus_dev/pyplusplus/code_creators/declaration_based.py pyplusplus_dev/pyplusplus/code_repository/__init__.py pyplusplus_dev/pyplusplus/cpptypes/tester.py pyplusplus_dev/pyplusplus/creators_factory/ctypes_creator.py pyplusplus_dev/pyplusplus/file_writers/writer.py pyplusplus_dev/pyplusplus/module_builder/ctypes_builder.py pyplusplus_dev/unittests/ctypes_pof_tester.py pyplusplus_dev/unittests/data/ctypes_pof/mydll.cpp pyplusplus_dev/unittests/data/ctypes_pof/mydll.h Added Paths: ----------- pyplusplus_dev/pyplusplus/code_creators/class_introduction.py pyplusplus_dev/pyplusplus/code_creators/embedded_code_repository.py pyplusplus_dev/pyplusplus/code_creators/fields_definition.py pyplusplus_dev/pyplusplus/code_creators/mem_fun_introduction.py pyplusplus_dev/pyplusplus/code_creators/methods_definition.py pyplusplus_dev/pyplusplus/code_creators/namespace_as_pyclass.py pyplusplus_dev/pyplusplus/code_repository/ctypes_cpp_utils.py Modified: pygccxml_dev/pygccxml/declarations/class_declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/class_declaration.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pygccxml_dev/pygccxml/declarations/class_declaration.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -457,7 +457,7 @@ def i_depend_on_them( self, recursive=True ): report_dependency = lambda *args: dependencies.dependency_info_t( self, *args ) - + answer = [] map( lambda base: answer.append( report_dependency( base.related_class, base.access_type, "base class" ) ) @@ -500,8 +500,8 @@ return 'wstring' else: return get_partial_name( self.name ) - - def find_noncopyable_vars( self ): + + def find_noncopyable_vars( self ): """returns list of all noncopyable variables""" import type_traits as tt#prevent cyclic dependencies logger = utils.loggers.cxx_parser @@ -524,9 +524,17 @@ cls = tt.class_traits.get_declaration( type_ ) if tt.is_noncopyable( cls ): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes member variable - class that is not copyable" % self.decl_string ) - noncopyable_vars.append( mvar ) + noncopyable_vars.append( mvar ) logger.debug( "__contains_noncopyable_mem_var - %s - false - doesn't contains noncopyable members" % self.decl_string ) return noncopyable_vars + @property + def has_vtable( self ): + """True, if class has virtual table, False otherwise""" + import calldef + return bool( self.calldefs( lambda f: isinstance( f, calldef.member_function_t ) \ + and f.virtuality != calldef.VIRTUALITY_TYPES.NOT_VIRTUAL + , recursive=False + , allow_empty=True ) ) class_types = ( class_t, class_declaration_t ) Modified: pygccxml_dev/unittests/data/core_cache.hpp =================================================================== --- pygccxml_dev/unittests/data/core_cache.hpp 2008-12-26 23:56:12 UTC (rev 1506) +++ pygccxml_dev/unittests/data/core_cache.hpp 2008-12-27 10:57:29 UTC (rev 1507) @@ -22,4 +22,4 @@ #endif//__core_cache_hpp__ -//touch//touch \ No newline at end of file +//touch//touch//touch \ No newline at end of file Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -146,4 +146,10 @@ from import_ import import_t from library_reference import library_reference_t from name_mappings import name_mappings_t - +from namespace_as_pyclass import namespace_as_pyclass_t +from class_introduction import class_introduction_t +from mem_fun_introduction import mem_fun_introduction_t +from mem_fun_introduction import vmem_fun_introduction_t +from fields_definition import fields_definition_t +from embedded_code_repository import embedded_code_repository_t +from methods_definition import methods_definition_t Added: pyplusplus_dev/pyplusplus/code_creators/class_introduction.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_introduction.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/class_introduction.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -0,0 +1,33 @@ +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import compound +import declaration_based +from pygccxml import declarations + +class class_introduction_t(compound.compound_t, declaration_based.declaration_based_t): + def __init__( self, class_ ): + compound.compound_t.__init__(self) + declaration_based.declaration_based_t.__init__( self, class_ ) + + def _create_impl(self): + result = [] + result.append( "class %s(ctypes.Structure):" % self.alias ) + result.append( self.indent( '"""class %s"""' % self.decl_identifier ) ) + result.append( self.indent( '#_fields_ = [] <-- class member variables definition list' ) ) + result.append( self.indent( '#_methods_ = {} <-- class non-virtual member functions definition list' ) ) + if self.creators: + result.append( self.indent( '' ) ) + result.append( compound.compound_t.create_internal_code( self.creators ) ) + + if isinstance( self.declaration.parent, declarations.namespace_t ) \ + and self.declaration.parent is not self.declaration.top_parent: #not a global namespace + result.append( '%(ns_full_name)s = %(name)s' + % dict( ns_full_name=self.complete_py_name, name=self.alias )) + return os.linesep.join( result ) + + def _get_system_headers_impl( self ): + return [] Modified: pyplusplus_dev/pyplusplus/code_creators/code_creator.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/code_creator.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/code_creators/code_creator.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -166,7 +166,7 @@ , os.linesep ) @staticmethod - def is_comment( line ): + def is_comment( line, language='C++' ): """ function that returns true if content of the line is comment, otherwise false. @@ -174,10 +174,19 @@ @param line: C++ source code @type line: str @rtype: bool + + @param language: the programming language, the line was written in. Possible values: C++, Python + @type line: str """ assert isinstance( line, types.StringTypes ) l = line.lstrip() - return l.startswith( '//' ) or l.startswith( '/*' ) + if language == 'C++': + return l.startswith( '//' ) or l.startswith( '/*' ) + elif language == 'Python': + return l.startswith( '#' ) + else: + raise RuntimeError( "Language %s is not supported. The possible values are: Python, C++" + % language ) @staticmethod def iif( condition, true_, false_ ): Modified: pyplusplus_dev/pyplusplus/code_creators/declaration_based.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -5,6 +5,7 @@ import algorithm import code_creator +from pygccxml import utils class declaration_based_t: """Code creator that is based on a declaration. @@ -18,12 +19,12 @@ @type parent: code_creator_t """ self._decl = declaration - + def _generate_valid_name(self, name=None): if name == None: name = self.declaration.name return algorithm.create_valid_name( name ) - + @property def declaration(self): """The declaration this code creator is based on. @@ -33,23 +34,39 @@ def _get_alias_impl( self ): return self.declaration.alias - - def _get_alias(self): - return self._get_alias_impl() + + def _get_alias(self): + return self._get_alias_impl() def _set_alias(self, alias): self.declaration.alias = alias alias = property( _get_alias, _set_alias ) - + + @utils.cached + def undecorated_decl_name( self ): + from pygccxml import msvc #prevent import on Linux + return msvc.undecorate_decl( self.declaration ) + + @utils.cached + def complete_py_name( self ): + aliases = [] + current = self.declaration + while current: + aliases.append( current.alias ) + current = current.parent + del aliases[-1] # :: from the global namespace + aliases.reverse() + return '.'.join( aliases ) + @property def decl_identifier( self ): return algorithm.create_identifier( self, self.declaration.partial_decl_string ) - + @property def documentation( self ): if None is self.declaration.documentation: return '' return self.declaration.documentation - + def get_user_headers( self, recursive=False, unique=False ): """return list of user header files to be included from the generated file""" return self.declaration.include_files Added: pyplusplus_dev/pyplusplus/code_creators/embedded_code_repository.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/embedded_code_repository.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/embedded_code_repository.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -0,0 +1,18 @@ +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import code_creator + +class embedded_code_repository_t(code_creator.code_creator_t): + """Creates Python import directive""" + def __init__( self, code_repository_module ): + code_creator.code_creator_t.__init__(self) + self.__code = code_repository_module.code + + def _create_impl(self): + return self.__code + + def _get_system_headers_impl( self ): + return [] Added: pyplusplus_dev/pyplusplus/code_creators/fields_definition.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/fields_definition.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/fields_definition.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -0,0 +1,31 @@ +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import code_creator +import declaration_based +from pygccxml import declarations + +class fields_definition_t(code_creator.code_creator_t, declaration_based.declaration_based_t): + def __init__( self, class_ ): + code_creator.code_creator_t.__init__(self) + declaration_based.declaration_based_t.__init__( self, class_ ) + + def _create_impl(self): + result = [] + result.append( '%(complete_py_name)s._fields_ = [ #class member variables definition list' + % dict( complete_py_name=self.complete_py_name ) ) + if self.declaration.has_vtable: + result.append( self.indent( '("_vtable_", ctypes.POINTER(ctypes.c_void_p)),' ) ) + result.append( self.indent( "#TODO: don't hide public member variables" ) ) + result.append( self.indent( "#TODO: how _fields_ should be defined in a class hierarchy" ) ) + result.append( self.indent( "#TODO: fix 64bit issue with calculating vtable pointer size" ) ) + result.append( self.indent( '("__hidden__", ctypes.c_char * %d),' + % ( self.declaration.byte_size - 4*int(self.declaration.has_vtable) ) ) ) + result.append( ']' ) + return os.linesep.join( result ) + + def _get_system_headers_impl( self ): + return [] Added: pyplusplus_dev/pyplusplus/code_creators/mem_fun_introduction.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/mem_fun_introduction.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/mem_fun_introduction.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -0,0 +1,41 @@ +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import code_creator +import declaration_based +from pygccxml import declarations + +class mem_fun_introduction_t(code_creator.code_creator_t, declaration_based.declaration_based_t): + def __init__( self, mem_fun ): + code_creator.code_creator_t.__init__(self) + declaration_based.declaration_based_t.__init__( self, mem_fun ) + + def _create_impl(self): + tmpl = ['def %(alias)s( self, *args ):'] + tmpl.append( self.indent('"""%(name)s"""') ) + tmpl.append( self.indent("return self._methods_['%(alias)s']( ctypes.byref( self ), *args )") ) + return os.linesep.join( tmpl ) \ + % dict( alias=self.declaration.alias, name=self.undecorated_decl_name ) + + def _get_system_headers_impl( self ): + return [] + +class vmem_fun_introduction_t(code_creator.code_creator_t, declaration_based.declaration_based_t): + def __init__( self, mem_fun ): + code_creator.code_creator_t.__init__(self) + declaration_based.declaration_based_t.__init__( self, mem_fun ) + + def _create_impl(self): + tmpl = ['def %(alias)s( self, *args ):'] + tmpl.append( self.indent('"""%(name)s"""') ) + tmpl.append( self.indent("return self._vtable_['%(ordinal)d'].%(alias)s( ctypes.byref( self ), *args )") ) + return os.linesep.join( tmpl ) \ + % dict( alias=self.declaration.alias + , name=self.undecorated_decl_name + , ordinal=0) + + def _get_system_headers_impl( self ): + return [] Added: pyplusplus_dev/pyplusplus/code_creators/methods_definition.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/methods_definition.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/methods_definition.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -0,0 +1,40 @@ +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import compound +import declaration_based +from pygccxml import declarations + +class methods_definition_t(compound.compound_t, declaration_based.declaration_based_t): + def __init__( self, class_ ): + compound.compound_t.__init__(self) + declaration_based.declaration_based_t.__init__( self, class_ ) + + @property + def mem_fun_factory_var_name(self): + return "mfcreator" + + def _create_impl(self): + result = [] + scope = declarations.algorithm.declaration_path( self.declaration ) + del scope[0] #del :: from the global namespace + + + result.append( '%(mem_fun_factory_var_name)s = mem_fun_factory( %(library_var_name)s, %(complete_py_name)s, "%(class_name)s", "%(ns)s" )' + % dict( mem_fun_factory_var_name=self.mem_fun_factory_var_name + , library_var_name=self.top_parent.library_var_name + , complete_py_name=self.complete_py_name + , class_name=self.declaration.name + , ns='::'.join(scope) ) ) + result.append( '%(complete_py_name)s._methods_ = { #class non-virtual member functions definition list' + % dict( complete_py_name=self.complete_py_name ) ) + result.append( compound.compound_t.create_internal_code( self.creators ) ) + result.append( '}' ) + result.append( 'del %s' % self.mem_fun_factory_var_name ) + return os.linesep.join( result ) + + def _get_system_headers_impl( self ): + return [] Added: pyplusplus_dev/pyplusplus/code_creators/namespace_as_pyclass.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/namespace_as_pyclass.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/namespace_as_pyclass.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -0,0 +1,25 @@ +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import compound +import declaration_based + +class namespace_as_pyclass_t(compound.compound_t, declaration_based.declaration_based_t): + def __init__( self, ns ): + compound.compound_t.__init__(self) + declaration_based.declaration_based_t.__init__( self, ns ) + + def _create_impl(self): + result = [] + result.append( "class %s:" % self.alias ) + result.append( self.indent( '"""namespace %s"""' % self.decl_identifier ) ) + if self.creators: + result.append( self.indent( "" ) ) + result.append( compound.compound_t.create_internal_code( self.creators ) ) + return os.linesep.join( result ) + + def _get_system_headers_impl( self ): + return [] Modified: pyplusplus_dev/pyplusplus/code_repository/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/__init__.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/code_repository/__init__.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -19,6 +19,7 @@ import convenience import return_range import call_policies +import ctypes_cpp_utils import ctypes_integration all = [ array_1 @@ -27,6 +28,7 @@ , call_policies , named_tuple , return_range + , ctypes_cpp_utils , ctypes_integration ] headers = map( lambda f: f.file_name, all ) Added: pyplusplus_dev/pyplusplus/code_repository/ctypes_cpp_utils.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/ctypes_cpp_utils.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_repository/ctypes_cpp_utils.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -0,0 +1,92 @@ +# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +file_name = "ctypes_cpp_utils.py" + +license = \ +"""# Copyright 2004-2008 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +""" + + +code = \ +""" +# what is the best way to treat overloaded constructors +class mem_fun_callable( object ): + def __init__(self, dll, name, restype=None, argtypes=None ): + self.name = name + self.func = getattr( dll, dll.undecorated_names[name] ) + self.func.restype = restype + self.func.argtypes = argtypes + + def __call__(self, *args, **keywd ): + return self.func( *args, **keywd ) + +class mem_fun_factory( object ): + def __init__( self, dll, wrapper, class_name, namespace='' ): + self.dll = dll + self.namespace = namespace + self.class_name = class_name + self.this_type = ctypes.POINTER( wrapper ) + + def __call__( self, name, **keywd ): + if 'argtypes' not in keywd: + keywd['argtypes'] = [ self.this_type ] + else: + keywd['argtypes'].insert( 0, self.this_type ) + return mem_fun_callable( self.dll, name, **keywd ) + + def __get_ns_name(self): + if self.namespace: + return self.namespace + '::' + else: + return '' + + def default_constructor( self ): + return self( '%(ns)s%(class_name)s::%(class_name)s(void)' + % dict( ns=self.__get_ns_name() + , class_name=self.class_name ) ) + + def constructor( self, argtypes_str, **keywd ): + return self( '%(ns)s%(class_name)s::%(class_name)s(%(args)s)' + % dict( ns=self.__get_ns_name() + , class_name=self.class_name + , args=argtypes_str ) + , **keywd ) + + def copy_constructor( self ): + return self( '%(ns)s%(class_name)s::%(class_name)s(%(class_name)s const &)' + % dict( ns=self.__get_ns_name() + , class_name=self.class_name ) + , argtypes=[self.this_type] ) + + def destructor( self ): + return self( '%(ns)s%(class_name)s::~%(class_name)s(void)' + % dict( ns=self.__get_ns_name() + , class_name=self.class_name ) ) + + def operator_assign( self ): + return self( '%(ns)s%(class_name)s & %(class_name)s::operator=(%(class_name)s const &)' + % dict( ns=self.__get_ns_name() + , class_name=self.class_name ) + , restype=self.this_type + , argtypes=[self.this_type] ) + + def method( self, name, restype_str=None, argtypes_str=None, **keywd ): + if None is restype_str: + restype_str = 'void' + if None is argtypes_str: + argtypes_str = 'void' + + return self( '%(return_)s %(ns)s%(class_name)s::%(method_name)s(%(args)s)' + % dict( return_=restype_str + , ns=self.__get_ns_name() + , class_name=self.class_name + , method_name=name + , args=argtypes_str ) + , **keywd ) +""" Modified: pyplusplus_dev/pyplusplus/cpptypes/tester.py =================================================================== --- pyplusplus_dev/pyplusplus/cpptypes/tester.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/cpptypes/tester.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -10,13 +10,13 @@ # GCCXML reports mangled and demangled names of the function, but it is not a cross platform( compile ) solution. # It looks like I will have to cause mspdb package to work ( from where ctypes loads dlls? ctypes.windll.msvcr90 ??? -mydll.name_mapping = name_mapping.data +mydll.undecorated_names = name_mapping.data # what is the best way to treat overloaded constructors -class public( object ): +class mem_fun_callable( object ): def __init__(self, dll, name, restype=None, argtypes=None ): self.name = name - self.func = getattr( dll, dll.name_mapping[name] ) + self.func = getattr( dll, dll.undecorated_names[name] ) self.func.restype = restype self.func.argtypes = argtypes @@ -35,7 +35,7 @@ keywd['argtypes'] = [ self.this_type ] else: keywd['argtypes'].insert( 0, self.this_type ) - return public( self.dll, name, **keywd ) + return mem_fun_callable( self.dll, name, **keywd ) def __get_ns_name(self): if self.namespace: Modified: pyplusplus_dev/pyplusplus/creators_factory/ctypes_creator.py =================================================================== --- pyplusplus_dev/pyplusplus/creators_factory/ctypes_creator.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/creators_factory/ctypes_creator.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -3,7 +3,7 @@ # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) - +import sort_algorithms import dependencies_manager from pygccxml import declarations from pyplusplus import decl_wrappers @@ -24,16 +24,18 @@ self.logger = _logging_.loggers.module_builder self.decl_logger = _logging_.loggers.declarations + self.global_ns = global_ns + self.__library_path = library_path self.__exported_symbols = exported_symbols - - self.__extmodule = code_creators.ctypes_module_t( global_ns ) + self.module = code_creators.ctypes_module_t( global_ns ) self.__dependencies_manager = dependencies_manager.manager_t(self.decl_logger) #~ prepared_decls = self.__prepare_decls( global_ns, doc_extractor ) #~ self.__decls = sort_algorithms.sort( prepared_decls ) self.curr_decl = global_ns - self.curr_code_creator = self.__extmodule + self.curr_code_creator = self.module + self.__class2introduction = {} def __print_readme( self, decl ): readme = decl.readme() @@ -48,6 +50,12 @@ for msg in readme: self.decl_logger.warn( "%s;%s" % ( decl, msg ) ) + def __should_generate_code( self, decl ): + if decl.ignore or decl.already_exposed: + return False + return True + + #~ def __prepare_decls( self, global_ns, doc_extractor ): #~ to_be_exposed = [] #~ for decl in declarations.make_flatten( global_ns ): @@ -74,7 +82,28 @@ #~ return to_be_exposed + def __contains_exported( self, decl ): + return bool( decl.decls( self.__should_generate_code, recursive=True, allow_empty=True ) ) + # - implement better 0(n) algorithm + def __add_class_introductions( self, cc, class_ ): + ci_creator = code_creators.class_introduction_t( class_ ) + self.__class2introduction[ class_ ] = ci_creator + cc.adopt_creator( ci_creator ) + classes = class_.classes( recursive=False, allow_empty=True) + classes = sort_algorithms.sort_classes( classes ) + for internal_class in classes: + if self.__contains_exported( internal_class ): + self.__add_class_introductions( ci_creator, internal_class ) + + # - implement better 0(n) algorithm + def __add_namespaces( self, cc, ns ): + ns_creator = code_creators.namespace_as_pyclass_t( ns ) + cc.adopt_creator( ns_creator ) + for internal_ns in ns.namespaces( recursive=False, allow_empty=True): + if self.__contains_exported( ns ): + self.__add_namespaces( ns_creator, internal_ns ) + def create(self ): """Create and return the module for the extension. @@ -82,20 +111,43 @@ @rtype: L{module_t<code_creators.module_t>} """ # Invoke the appropriate visit_*() method on all decls - self.__extmodule.adopt_creator( code_creators.import_t( 'ctypes' ) ) - self.__extmodule.adopt_creator( code_creators.separator_t() ) - self.__extmodule.adopt_creator( code_creators.library_reference_t( self.__library_path ) ) - self.__extmodule.adopt_creator( code_creators.name_mappings_t( self.__exported_symbols ) ) - self.__extmodule.adopt_creator( code_creators.separator_t() ) + ccc = self.curr_code_creator + ccc.adopt_creator( code_creators.import_t( 'ctypes' ) ) + ccc.adopt_creator( code_creators.separator_t() ) + ccc.adopt_creator( code_creators.library_reference_t( self.__library_path ) ) + ccc.adopt_creator( code_creators.name_mappings_t( self.__exported_symbols ) ) + ccc.adopt_creator( code_creators.separator_t() ) + #adding namespaces + for ns in self.global_ns.namespaces( recursive=False, allow_empty=True): + if self.__contains_exported( ns ): + self.__add_namespaces( ccc, ns ) + #adding class introductions + f = lambda cls: self.__should_generate_code( cls ) \ + and isinstance( cls.parent, declarations.namespace_t ) + ns_classes = self.global_ns.classes( f, recursive=True, allow_empty=True) + ns_classes = sort_algorithms.sort_classes( ns_classes ) + for class_ in ns_classes: + if self.__contains_exported( ns ): + self.__add_class_introductions( ccc, class_ ) + ccc.adopt_creator( code_creators.embedded_code_repository_t( code_repository.ctypes_cpp_utils ) ) + declarations.apply_visitor( self, self.curr_decl ) self.__dependencies_manager.inform_user() - return self.__extmodule + return self.module def visit_member_function( self ): self.__dependencies_manager.add_exported( self.curr_decl ) + cls_intro_cc = self.__class2introduction[ self.curr_decl.parent ] + cls_intro_cc.adopt_creator( code_creators.mem_fun_introduction_t( self.curr_decl ) ) + #~ if self.curr_decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: + #~ cls_intro_cc.adopt_creator( code_creators.mem_fun_introduction_t( self.curr_decl ) ) + #~ elif self.curr_decl.virtuality == VIRTUALITY_TYPES.VIRTUAL: + #~ cls_intro_cc.adopt_creator( code_creators.vmem_fun_introduction_t( self.curr_decl ) ) + #~ else: + #~ pass def visit_constructor( self ): self.__dependencies_manager.add_exported( self.curr_decl ) @@ -118,17 +170,33 @@ def visit_class_declaration(self ): self.__dependencies_manager.add_exported( self.curr_decl ) - def visit_class(self ): + def visit_class(self): self.__dependencies_manager.add_exported( self.curr_decl ) + #fields definition should be recursive using the visitor + self.curr_code_creator.adopt_creator( code_creators.fields_definition_t( self.curr_decl ) ) + self.curr_code_creator.adopt_creator( code_creators.methods_definition_t( self.curr_decl ) ) + class_ = self.curr_decl + for decl in self.curr_decl.decls( recursive=False, allow_empty=True ): + if self.__should_generate_code( decl ): + self.curr_decl = decl + declarations.apply_visitor( self, decl ) + self.curr_decl = class_ def visit_enumeration(self): self.__dependencies_manager.add_exported( self.curr_decl ) - def visit_namespace(self): - self.__dependencies_manager.add_exported( self.curr_decl ) - def visit_typedef(self): self.__dependencies_manager.add_exported( self.curr_decl ) def visit_variable(self): self.__dependencies_manager.add_exported( self.curr_decl ) + + def visit_namespace(self ): + ns = self.curr_decl + for decl in self.curr_decl.decls( recursive=False, allow_empty=True ): + if isinstance( decl, declarations.namespace_t) or self.__should_generate_code( decl ): + self.curr_decl = decl + declarations.apply_visitor( self, decl ) + self.curr_decl = ns + + Modified: pyplusplus_dev/pyplusplus/file_writers/writer.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/writer.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/file_writers/writer.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -16,14 +16,14 @@ class writer_t(object): """Base class for all module/code writers. - + All writers should have similar usage:: - + w = writer_class(module, file, ...) w.write() """ logger = _logging_.loggers.file_writer - + def __init__(self, extmodule, files_sum_repository=None, encoding='ascii'): object.__init__(self) self.__extmodule = extmodule @@ -32,14 +32,15 @@ if None is files_sum_repository: self.__files_sum_repository = md5sum_repository.dummy_repository_t() self.__exposed_decls_db = utils.exposed_decls_db_t() - self.__exposed_decls_db.register_decls( extmodule.global_ns - , extmodule.specially_exposed_decls ) + if isinstance( self.__extmodule, code_creators.bpmodule_t ): + self.__exposed_decls_db.register_decls( extmodule.global_ns + , extmodule.specially_exposed_decls ) @property def encoding( self ): """encoding name used to write generated code to files""" return self.__encoding - + @property def extmodule(self): """The root of the code creator tree ( code_creators.module_t )""" @@ -52,17 +53,17 @@ def write(self): """ Main write method. Should be overridden by derived classes. """ raise NotImplementedError() - + @staticmethod def create_backup(fpath): """creates backup of the file, by renaming it to C{fpath + ~}""" if not os.path.exists( fpath ): - return + return backup_fpath = fpath + '~' if os.path.exists( backup_fpath ): os.remove( backup_fpath ) os.rename( fpath, backup_fpath ) - + def write_code_repository(self, dir): """creates files defined in L{code_repository} package""" system_headers = self.extmodule.get_system_headers( recursive=True ) @@ -72,7 +73,7 @@ self.write_file( os.path.join( dir, cr.file_name ), cr.code ) #named_tuple.py is a special case :-( self.write_file( os.path.join( dir, code_repository.named_tuple.file_name ) - , code_repository.named_tuple.code ) + , code_repository.named_tuple.code ) @staticmethod def write_file( fpath, content, files_sum_repository=None, encoding='ascii' ): """Write a source file. @@ -99,8 +100,8 @@ fcontent_new.append( os.linesep ) #keep gcc happy fcontent_new = ''.join( fcontent_new ) if not isinstance( fcontent_new, unicode ): - fcontent_new = unicode( fcontent_new, encoding ) - + fcontent_new = unicode( fcontent_new, encoding ) + new_hash_value = None curr_hash_value = None if files_sum_repository: @@ -122,9 +123,9 @@ writer_t.logger.debug( 'file was not changed( content ) - done( %f seconds )' % ( time.clock() - start_time ) ) return - + writer_t.logger.debug( 'file changed or it does not exist' ) - + writer_t.create_backup( fpath ) f = codecs.open( fpath, 'w+b', encoding ) f.write( fcontent_new ) @@ -132,7 +133,7 @@ if new_hash_value: files_sum_repository.update_value( fname, new_hash_value ) writer_t.logger.info( 'file "%s" - updated( %f seconds )' % ( fname, time.clock() - start_time ) ) - + def get_user_headers( self, creators ): headers = [] creators = filter( lambda creator: isinstance( creator, code_creators.declaration_based_t ) @@ -143,5 +144,5 @@ def save_exposed_decls_db( self, file_path ): self.__exposed_decls_db.save( file_path ) - - + + Modified: pyplusplus_dev/pyplusplus/module_builder/ctypes_builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/ctypes_builder.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/pyplusplus/module_builder/ctypes_builder.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -84,12 +84,12 @@ is_exported = lambda d: msvc.undecorate_decl( d ) in undecorated included_decls = set() - included_decls.update( self.global_ns.calldefs( is_exported, allow_empty=True ) ) - included_decls.update( self.global_ns.variables( is_exported, allow_empty=True ) ) + included_decls.update( self.global_ns.calldefs( is_exported, allow_empty=True, recursive=True ) ) + included_decls.update( self.global_ns.variables( is_exported, allow_empty=True, recursive=True ) ) for d in included_decls: d.include() - if isinstance( d, decls_package.class_t ): + if isinstance( d.parent, decls_package.class_t ): d.parent.include() def build_code_creator( self, library_path, doc_extractor=None ): @@ -120,7 +120,6 @@ @param file_name: file name @type file_name: string """ - self.__merge_user_code() file_writers.write_file( self.code_creator, file_name, encoding=self.encoding ) Modified: pyplusplus_dev/unittests/ctypes_pof_tester.py =================================================================== --- pyplusplus_dev/unittests/ctypes_pof_tester.py 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/unittests/ctypes_pof_tester.py 2008-12-27 10:57:29 UTC (rev 1507) @@ -16,12 +16,18 @@ self.project_dir = os.path.join( autoconfig.data_directory, 'ctypes_pof' ) self.header = os.path.join( self.project_dir, 'mydll.h' ) self.symbols_file = os.path.join( self.project_dir, 'release', 'mydll.dll' ) + self.module_name = 'ctypes_pof' def test(self): mb = ctypes_module_builder_t( [self.header], self.symbols_file, autoconfig.cxx_parsers_cfg.gccxml ) + #~ mb.global_ns.include() mb.build_code_creator( self.symbols_file ) - print mb.code_creator.create() + mb.write_module( os.path.join( autoconfig.build_directory, self.module_name + '.py' ) ) + #mb.code_creator.create() + sys.path.append( autoconfig.build_directory ) + import ctypes_pof + def create_suite(): suite = unittest.TestSuite() if 'win' in sys.platform: Modified: pyplusplus_dev/unittests/data/ctypes_pof/mydll.cpp =================================================================== --- pyplusplus_dev/unittests/data/ctypes_pof/mydll.cpp 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/unittests/data/ctypes_pof/mydll.cpp 2008-12-27 10:57:29 UTC (rev 1507) @@ -2,6 +2,8 @@ #include "windows.h" #include <iostream> +namespace pof{ + number_t::number_t() : m_value(0) { @@ -38,6 +40,10 @@ return std::auto_ptr<number_t>( new number_t( *this ) ); } +} + +using namespace pof; + void do_smth( number_aptr_t& ){ } Modified: pyplusplus_dev/unittests/data/ctypes_pof/mydll.h =================================================================== --- pyplusplus_dev/unittests/data/ctypes_pof/mydll.h 2008-12-26 23:56:12 UTC (rev 1506) +++ pyplusplus_dev/unittests/data/ctypes_pof/mydll.h 2008-12-27 10:57:29 UTC (rev 1507) @@ -2,12 +2,14 @@ #include <memory> +namespace pof{ + class __declspec(dllexport) number_t{ public: number_t(); explicit number_t(int value); virtual ~number_t(); - void print_it() const; + virtual void print_it() const; int get_value() const; int get_value(){ return m_value; } void set_value(int x); @@ -18,8 +20,9 @@ int m_value; }; -template class __declspec(dllexport) std::auto_ptr< number_t >; +} +template class __declspec(dllexport) std::auto_ptr< pof::number_t >; -typedef std::auto_ptr< number_t > number_aptr_t; +typedef std::auto_ptr< pof::number_t > number_aptr_t; -void __declspec(dllexport) do_smth( number_aptr_t& ); \ No newline at end of file +void __declspec(dllexport) do_smth( number_aptr_t& ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |