[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.
|