[pygccxml-commit] SF.net SVN: pygccxml:[1386] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2008-08-08 12:18:11
|
Revision: 1386 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1386&view=rev Author: roman_yakovenko Date: 2008-08-08 12:18:18 +0000 (Fri, 08 Aug 2008) Log Message: ----------- adding new features: exposing anonymous structs and anonymous unions, exposing variables, that has union as a type Modified Paths: -------------- pyplusplus_dev/docs/documentation/www_configuration.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py pyplusplus_dev/pyplusplus/messages/warnings_.py pyplusplus_dev/pyplusplus/module_builder/builder.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp pyplusplus_dev/unittests/module_body_tester.py pyplusplus_dev/unittests/unnamed_classes_tester.py Added Paths: ----------- pyplusplus_dev/docs/documentation/ctypes/ pyplusplus_dev/unittests/data/unions_to_be_exported.hpp pyplusplus_dev/unittests/unions_tester.py Removed Paths: ------------- pyplusplus_dev/docs/documentation/ctypes_integration.rest Deleted: pyplusplus_dev/docs/documentation/ctypes_integration.rest =================================================================== --- pyplusplus_dev/docs/documentation/ctypes_integration.rest 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/docs/documentation/ctypes_integration.rest 2008-08-08 12:18:18 UTC (rev 1386) @@ -1,148 +0,0 @@ -================== -ctypes integration -================== - -.. contents:: Table of contents - ------------- -Introduction ------------- - -`Boost.Python`_ is really a very powerful library, but if you are working -with code written in plain "C" - you've got a problem. You have to create -wrappers for almost every function or variable. - -In general, if you want to work with plain "C" code from `Python`_ -you don't have to create any wrapper - you can use `ctypes`_ package. - -About ctypes ------------- -`ctypes`_ is a foreign function library for Python. It provides C -compatible data types, and allows to call functions in dlls/shared -libraries. It can be used to wrap these libraries in pure Python. - - - -The idea behind "ctypes integration" functionality is simple: you -configure `Py++`_ to expose address of the variables or return -values, as integer and than you can use `ctypes`_ `from_address`_ -functionality to access the data. - -Obviously, this approach has its price: - -* it could be very dangerous - you can corrupt your application memory - -* managing memory is not something a typical `Python`_ user get used to. - It is too "low level". - -In my opinion, the better way to go is to "mix": - -1. expose your native code using `Boost.Python`_ and "ctypes integration" - functionality - -2. use `ctypes`_ module to access your data - -3. create high level API: the wrappers, which will ensure the constraints - and will provide more "natural" interface - --------------- -Usage examples --------------- - -Variables ---------- - -Lets say you have the following C++ code: - - .. code-block:: C++ - - struct bytes_t{ - bytes_t(){ - data = new int[5]; - for(int i=0; i<5; i++){ - data[i] = i; - } - } - ... - int* data; - static int* x; - }; - - //somewhere in a cpp file - int* bytes_t::x = new int( 1997 ); - -In order to get access to the ``bytes_t::data`` and ``bytes_t::x`` you -have to turn on ``expose_address`` property to ``True``: - - .. code-block:: Python - - mb = module_builder_t( ... ) - bytes = mb.class_( 'bytes_t' ) - bytes.vars().expose_address = True - -`Py++`_ will generate code, which will expose the address of the variables. - -and now it is a time to show some `ctypes`_ magic: - - .. code-block:: Python - - import ctypes - import your_module as m - - bytes = m.bytes_t() - - data_type = ctypes.POINTER( ctypes.c_int ) - data = data_type.from_address( bytes.data ) - for j in range(5): - print '%d : %d' % ( j, data[j] ) - - data_type = ctypes.POINTER( ctypes.c_int ) - data = data_type.from_address( m.bytes_t.x ) - print x.contents.value - - -"this" pointer --------------- - -`Py++`_ can expose "this" pointer value to `Python`_: - - .. code-block:: Python - - mb = module_builder_t( ... ) - mb.class_( 'bytes_t' ).expose_this = True - -and the usage example: - - .. code-block:: Python - - import ctypes - import your_module as m - - print m.bytes_t().this - - -Warning: I hope you know what you are doing, otherwise don't blame me :-) - ------------------ -Future directions ------------------ - -The functionality is going to be developed father and I intend to add -next features: - -* to expose the result of "sizeof" applied on a class or variable - -* to add new call policy, which will return value of a pointer as integer - -* to port this functionality to 64bit systems - -* to add support for unions - -.. _`ctypes` : http://docs.python.org/lib/module-ctypes.html -.. _`from_address` : http://docs.python.org/lib/ctypes-data-types.html -.. _`Py++` : ./../pyplusplus.html -.. _`pygccxml` : ./../../pygccxml/pygccxml.html -.. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html -.. _`Python`: http://www.python.org -.. _`GCC-XML`: http://www.gccxml.org - Modified: pyplusplus_dev/docs/documentation/www_configuration.py =================================================================== --- pyplusplus_dev/docs/documentation/www_configuration.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/docs/documentation/www_configuration.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -8,5 +8,4 @@ , 'best_practices' : 'best practices' , 'multi_module_development' : 'multi-module development' , 'split_module' : 'splitting generated code to files' - , 'ctypes_integration' : 'ctypes integration' } Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -54,7 +54,7 @@ def _get_create_with_signature(self): if None is self._create_with_signature: self._create_with_signature = bool( self.overloads ) - + if not self._create_with_signature and declarations.templates.is_instantiation( self.name ): self._create_with_signature = True @@ -73,7 +73,7 @@ self._create_with_signature \ = bool( self.parent.calldefs( self.name, recursive=False, allow_empty=True ) ) return self._create_with_signature - + def _set_create_with_signature(self, create_with_signature): self._create_with_signature = create_with_signature create_with_signature = property( _get_create_with_signature, _set_create_with_signature @@ -159,6 +159,8 @@ return '' def _exportable_impl( self ): + if not self.parent.name: + return messages.W1057 % str( self ) all_types = [ arg.type for arg in self.arguments ] all_types.append( self.return_type ) for some_type in all_types: @@ -398,7 +400,7 @@ included = filter( lambda decl: decl.ignore == False, oper.class_types ) if not included: return messages.W1052 % str(oper) - + return '' class member_operator_t( declarations.member_operator_t, calldef_t ): Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -370,10 +370,16 @@ def _exportable_impl( self ): if not self.name: - return messages.W1018 - #it is possible to do so, but not for unnamed classes defined under namespace. + named_parent = declarations.get_named_parent( self ) + if not named_parent: + return messages.W1057 % str( self ) + if isinstance( named_parent, declarations.namespace_t ): + return messages.W1018 % str( self ) if self.class_type == declarations.CLASS_TYPES.UNION: - return messages.W1054 + if self.is_wrapper_needed(): + return messages.W1059 % str( self ) + if self.name: + return messages.W1060 % str( self ) if isinstance( self.parent, declarations.namespace_t ): return '' if not self in self.parent.public_members: @@ -587,14 +593,7 @@ if isinstance( member, declarations.destructor_t ): continue if isinstance( member, declarations.variable_t ): - if member.bits: - explanation.append( messages.W1024 % member.name ) - if declarations.is_pointer( member.type ): - explanation.append( messages.W1025 % member.name ) - if declarations.is_reference( member.type ): - explanation.append( messages.W1026 % member.name ) - if declarations.is_array( member.type ): - explanation.append( messages.W1027 % member.name) + explanation.extend( member.is_wrapper_needed() ) if isinstance( member, declarations.class_t ) and member.is_wrapper_needed(): explanation.append( messages.W1028 % member.name) if isinstance( member, declarations.calldef_t ): @@ -636,3 +635,16 @@ self._expose_this = new_value expose_this = property( _get_expose_this, _set_expose_this , doc="boolean, if True an object address( this pointer ) will be exposed to Python as integer.") + + @property + def introduces_new_scope(self): + """returns True, if during exposing this class, new scope will be created + + For example, anonymous structs will be exposed in a parent scope. + """ + if not self.name: + return False + elif self.class_type == declarations.CLASS_TYPES.UNION: + return False + else: + return True Modified: pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -75,3 +75,8 @@ if len( set( name2value.keys() ) ) != len( set( name2value.values() ) ): msgs.append( messages.W1032 ) return msgs + + def _exportable_impl( self ): + if not self.parent.name: + return messages.W1057 % str( self ) + return '' Modified: pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -23,7 +23,8 @@ self._is_read_only = None self._use_make_functions = None self._expose_address = None - + self._expose_value = None + __call_policies_doc__ = \ """There are usecase, when exporting member variable forces Py++ to create accessors functions. Sometime, those functions requires call policies. @@ -56,7 +57,7 @@ def get_setter_call_policies( self ): if None is self._getter_call_policies: if self.apply_smart_ptr_wa or self.use_make_functions: - self._setter_call_policies = call_policies.default_call_policies() + self._setter_call_policies = call_policies.default_call_policies() return self._setter_call_policies def set_setter_call_policies( self, call_policies ): self._setter_call_policies = call_policies @@ -65,15 +66,15 @@ __use_make_functions_doc__ = \ """Generate code using make_getter and make_setter functions - + Basically you don't need to use this, untill you have one of the next use-cases: * member variable is smart pointer - in this case Boost.Python has small problem to expose it right. Using the functions is a work around to the problem. * member variable defined custom r-value converter - may be you don't know - but the conversion is applied only on functions arguments. So you need to + but the conversion is applied only on functions arguments. So you need to use make_getter/make_setter in order to allow user to enjoy from the conversion. - + Setting "apply_smart_ptr_wa" and/or "use_make_functions" to "True" will tell Py++ to generate such code. """ @@ -92,32 +93,64 @@ use_make_functions = property( get_use_make_functions, set_use_make_functions , doc=__use_make_functions_doc__) + def __should_be_exposed_by_address_only(self): + type_ = declarations.remove_alias( self.type ) + type_ = declarations.remove_const( type_ ) + type_ = declarations.remove_pointer( type_ ) + if not declarations.class_traits.is_my_case( type_ ): + return False + cls = declarations.class_traits.get_declaration( type_ ) + if cls.class_type == declarations.CLASS_TYPES.UNION: + return True + elif not cls.name: + return True + else: + return False + __expose_address_doc__ = \ """There are some cases when Boost.Python doesn't provide a convenient way to expose the variable to Python. For example: - + double* x[10]; //or char* buffer; //in case you want to modify the buffer in place - - In this cases Py++ doesn't help too. In these cases it is possible to expose + + In this cases Py++ doesn't help too. In these cases it is possible to expose the actual address of the variable. After that, you can use built-in "ctypes" - package to edit the content of the variable. + package to edit the content of the variable. """ def get_expose_address( self ): + if None is self._expose_address: + self._expose_address = self.__should_be_exposed_by_address_only() return self._expose_address def set_expose_address( self, value ): self._expose_address = value expose_address = property( get_expose_address, set_expose_address , doc= __expose_address_doc__ ) - + __expose_value_doc__ = \ + """Boost.Python is not able to expose unions. Using ctypes module + it is possible to get access to the data stored in a variable, which + has some union type. + + This property controls whether Py++ should expose the variable value + or not. In case, this variable has type union, this property will be False. + """ + def get_expose_value( self ): + if None is self._expose_value: + self._expose_value = not self.__should_be_exposed_by_address_only() + return self._expose_value + def set_expose_value( self, value ): + self._expose_value = value + expose_value = property( get_expose_value, set_expose_value + , doc= __expose_value_doc__ ) + def __find_out_is_read_only(self): type_ = declarations.remove_alias( self.type ) - + if isinstance( type_, declarations.const_t ): return True - + if declarations.is_pointer( type_ ): type_ = declarations.remove_pointer( type_ ) @@ -126,16 +159,16 @@ if isinstance( type_, declarations.const_t ): return True - + if self.apply_smart_ptr_wa: return False #all smart pointers has assign operator - + if isinstance( type_, declarations.declarated_t ) \ and isinstance( type_.declaration, declarations.class_t ) \ and not declarations.has_public_assign( type_.declaration ): return True return False - + def get_is_read_only( self ): if None is self._is_read_only: self._is_read_only = self.__find_out_is_read_only() @@ -145,8 +178,9 @@ is_read_only = property( get_is_read_only, set_is_read_only ) def _exportable_impl( self ): - if self.name == 'f': - i = 0 + if not self.parent.name and self.is_wrapper_needed(): + #return messages.W1057 % str( self ) + return messages.W1058 % str( self ) if not self.name: return messages.W1033 if self.bits == 0 and self.name == "": @@ -172,6 +206,8 @@ cls = declarations.class_traits.get_declaration( type_ ) if not cls.name: return messages.W1038 + #if cls.class_type == declarations.CLASS_TYPES.UNION: + # return messages.W1061 % ( str( self ), str( cls ) ) if isinstance( self.parent, declarations.class_t ): if self.access_type != declarations.ACCESS_TYPES.PUBLIC: return messages.W1039 @@ -182,3 +218,19 @@ if python_traits.is_immutable( item_type_no_ptr ): return messages.W1056 return '' + + def is_wrapper_needed(self): + """returns an explanation( list of str ) why wrapper is needed. + + If wrapper is not needed than [] will be returned. + """ + explanation = [] + if self.bits: + explanation.append( messages.W1024 % self.name ) + if declarations.is_pointer( self.type ): + explanation.append( messages.W1025 % self.name ) + if declarations.is_reference( self.type ): + explanation.append( messages.W1026 % self.name ) + if declarations.is_array( self.type ): + explanation.append( messages.W1027 % self.name) + return explanation Modified: pyplusplus_dev/pyplusplus/messages/warnings_.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/warnings_.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/messages/warnings_.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -99,11 +99,11 @@ W1016 = warning( 'Py++ does not exports non-const casting operators with user defined type as return value. ' - 'This could be change in future.' ) + 'This could be changed in future.' ) W1017 = compilation_error( "Py++ doesn't export non-public casting operators." ) -W1018 = compilation_error( 'Py++ can not expose unnamed classes.' ) +W1018 = compilation_error( 'Py++ can not expose anonymous class "%s", declared in a namespace.' ) W1019 = compilation_error( 'Py++ can not expose private class.' ) @@ -139,7 +139,7 @@ "http://boost.org/libs/python/todo.html#support-for-enums-with-duplicate-values . " "The quick work around is to add new class variable to the exported enum, from Python. " ) -W1033 = compilation_error( "Py++ can not expose unnamed variables" ) +W1033 = compilation_error( "Py++ can not expose anonymous variables" ) W1034 = compilation_error( "Py++ can not expose alignment bit." ) @@ -151,7 +151,7 @@ "Boost.Python library can not expose variables, which are pointer to function." " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." ) -W1038 = compilation_error( "Py++ can not expose variables of with unnamed type." ) +W1038 = compilation_error( "Py++ can not expose variables of with anonymous type." ) W1039 = compilation_error( "Py++ doesn't expose private or protected member variables." ) @@ -222,6 +222,21 @@ W1056 = compilation_error( "Py++ can not expose array of pointers of Python immutable types. Take a look on 'ctypes integration' feature." ) +W1057 = compilation_error( 'Py++ can not expose "%s" - it does not belong to named class.' ) + +W1058 = compilation_error( 'Py++ can not expose "%s" it belongs to anonymous class' + ' and requires additional code to expose.' + ' This could be changed in future.') + +W1059 = compilation_error( 'Py++ can not expose "%s" - it requires additional code to expose.' + ' This could be changed in future.') + +W1060 = compilation_error( 'Py++ can not expose "%s" - it has name, Py++ only exposes anonymous unions.' + ' This could be changed in future.') + +W1061 = compilation_error( 'Py++ can not expose "%s" - its type is "%s".' + ' This could be changed in future.') + warnings = globals() all_warning_msgs = [] Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -6,7 +6,7 @@ import os import sys import time - +import types import warnings from pygccxml import parser @@ -97,7 +97,7 @@ self.__registrations_code_head = [] self.__registrations_code_tail = [] - + @property def global_ns( self ): """reference to global namespace""" @@ -108,19 +108,19 @@ return self.__encoding def register_module_dependency( self, other_module_generated_code_dir ): - """``already_exposed`` solution is pretty good when you mix hand-written - modules with Py++ generated. It doesn't work/scale for "true" - multi-module development. This is exactly the reason why ``Py++``_ + """``already_exposed`` solution is pretty good when you mix hand-written + modules with Py++ generated. It doesn't work/scale for "true" + multi-module development. This is exactly the reason why ``Py++``_ offers "semi automatic" solution. - For every exposed module, ``Py++``_ generates "exposed_decl.pypp.txt" file. - This file contains the list of all parsed declarations and whether they - were included or excluded. Later, when you work on another module, you - can tell ``Py++``_ that the current module depends on the previously - generated one. ``Py++``_ will load "exposed_decl.pypp.txt" file and + For every exposed module, ``Py++``_ generates "exposed_decl.pypp.txt" file. + This file contains the list of all parsed declarations and whether they + were included or excluded. Later, when you work on another module, you + can tell ``Py++``_ that the current module depends on the previously + generated one. ``Py++``_ will load "exposed_decl.pypp.txt" file and update the declarations. """ - + db = utils.exposed_decls_db_t() db.load( other_module_generated_code_dir ) db.update_decls( self.global_ns ) @@ -305,6 +305,23 @@ else: self.__registrations_code_head.append( code ) + def add_constants( self, **keywds ): + """adds code that exposes some constants to Python. + + For example: + mb.add_constants( version='"1.2.3"' ) + or + mb.add_constants( **{ version:'"1.2.3"' } ) + will generate next code: + boost::python::scope().attr("version") = "1.2.3"; + """ + tmpl = 'boost::python::scope().attr("%(name)s") = %(value)s;' + for name, value in keywds.items(): + if not isinstance( value, types.StringTypes ): + value = str( value ) + self.add_registration_code( tmpl % dict( name=name, value=value) ) + + def __merge_user_code( self ): for code in self.__declarations_code_tail: self.code_creator.add_declaration_code( code, -1 ) @@ -365,24 +382,24 @@ This could speed-up code generation process by 10-15%. """ self.__merge_user_code() - - files_sum_repository = None + + files_sum_repository = None if use_files_sum_repository: cache_file = os.path.join( dir_name, self.code_creator.body.name + '.md5.sum' ) files_sum_repository = file_writers.cached_repository_t( cache_file ) - + written_files = [] if None is huge_classes: - written_files = file_writers.write_multiple_files( + written_files = file_writers.write_multiple_files( self.code_creator , dir_name , files_sum_repository=files_sum_repository , encoding=self.encoding) else: - written_files = file_writers.write_class_multiple_files( + written_files = file_writers.write_class_multiple_files( self.code_creator , dir_name - , huge_classes + , huge_classes , files_sum_repository=files_sum_repository , encoding=self.encoding) self.__work_on_unused_files( dir_name, written_files, on_unused_file_found ) @@ -411,18 +428,18 @@ This could speed-up code generation process by 10-15%. """ self.__merge_user_code() - - files_sum_repository = None + + files_sum_repository = None if use_files_sum_repository: cache_file = os.path.join( dir_name, self.code_creator.body.name + '.md5.sum' ) files_sum_repository = file_writers.cached_repository_t( cache_file ) - + written_files = file_writers.write_balanced_files( self.code_creator , dir_name , number_of_buckets=number_of_files , files_sum_repository=files_sum_repository , encoding=self.encoding) - + self.__work_on_unused_files( dir_name, written_files, on_unused_file_found ) return written_files @@ -470,7 +487,7 @@ , header_file=header_file , recursive=recursive) var = variable - + def variables( self, name=None, function=None, type=None, header_dir=None, header_file=None, recursive=None ): """Please see L{decl_wrappers.scopedef_t} class documentation""" return self.global_ns.variables( name=name @@ -480,7 +497,7 @@ , header_file=header_file , recursive=recursive) vars = variables - + def calldef( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ): """Please see L{decl_wrappers.scopedef_t} class documentation""" return self.global_ns.calldef( name=name @@ -651,7 +668,7 @@ , header_file=header_file , recursive=recursive ) free_fun = free_function - + def free_functions( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ): """Please see L{decl_wrappers.namespace_t} class documentation""" return self.global_ns.free_functions( name=name @@ -662,7 +679,7 @@ , header_file=header_file , recursive=recursive) free_funs = free_functions - + def free_operator( self, name=None, function=None, symbol=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ): """Please see L{decl_wrappers.namespace_t} class documentation""" return self.global_ns.free_operator( name=name Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -19,16 +19,6 @@ ACCESS_TYPES = declarations.ACCESS_TYPES VIRTUALITY_TYPES = declarations.VIRTUALITY_TYPES -#TODO: add print decl_wrapper.readme messages -#class Foo{ -# union { -# struct { -# float r,g,b,a; -# }; -# float val[4]; -# }; -# }; - class creator_t( declarations.decl_visitor_t ): """Creating code creators. @@ -561,7 +551,11 @@ exportable_members = self.curr_decl.get_exportable_members(sort_algorithms.sort) wrapper = None - cls_cc = code_creators.class_t( class_inst=self.curr_decl ) + cls_cc = None + if cls_decl.introduces_new_scope: + cls_cc = code_creators.class_t( class_inst=self.curr_decl ) + else: + cls_cc = self.curr_code_creator if self.curr_decl.is_wrapper_needed(): wrapper = code_creators.class_wrapper_t( declaration=self.curr_decl @@ -591,7 +585,8 @@ exposed = self.expose_overloaded_mem_fun_using_macro( cls_decl, cls_cc ) - cls_parent_cc.adopt_creator( cls_cc ) + if cls_decl.introduces_new_scope: + cls_parent_cc.adopt_creator( cls_cc ) self.curr_code_creator = cls_cc if cls_decl.expose_this: @@ -672,6 +667,9 @@ self.curr_code_creator.adopt_creator( creator_type(self.curr_decl) ) return + if not self.curr_decl.expose_value: + return + if declarations.is_array( self.curr_decl.type ): if self._register_array_1( self.curr_decl.type ): array_1_registrator = code_creators.array_1_registrator_t( array_type=self.curr_decl.type ) Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -6,7 +6,7 @@ """defines class, which informs user about used, but unexposed declarations""" import os -from pyplusplus import utils +from pyplusplus import utils from pyplusplus import messages from pygccxml import declarations from pyplusplus import decl_wrappers @@ -17,19 +17,19 @@ object.__init__( self ) self.__exported_decls = [] self.__logger = logger - + def add_exported( self, decl ): - self.__exported_decls.append( decl ) + self.__exported_decls.append( decl ) def __select_duplicate_aliases( self, decls ): duplicated = {} for decl in decls: if not duplicated.has_key( decl.alias ): duplicated[ decl.alias ] = set() - duplicated[ decl.alias ].add( decl ) + duplicated[ decl.alias ].add( decl ) for alias, buggy_decls in duplicated.items(): if 1 == len( buggy_decls ): - del duplicated[ alias ] + del duplicated[ alias ] return duplicated def __report_duplicate_aliases_impl( self, control_decl, duplicated ): @@ -39,7 +39,7 @@ warning = messages.W1047 % ( control_decl.alias , os.linesep.join( map( str, buggy_decls ) ) ) self.__logger.warn( "%s;%s" % ( control_decl, warning ) ) - + if isinstance( control_decl, declarations.class_t ): query = lambda i_decl: isinstance( i_decl, declarations.class_types ) \ and i_decl.ignore == False @@ -55,7 +55,7 @@ duplicated = self.__select_duplicate_aliases( decls ) for decl in decls: self.__report_duplicate_aliases_impl( decl, duplicated ) - + def __is_std_decl( self, decl ): #Every class under std should be exported by Boost.Python and\\or Py++ #Also this is not the case right now, I prefer to hide the warnings @@ -80,7 +80,7 @@ dependencies = filter( lambda d: d.access_type != declarations.ACCESS_TYPES.PRIVATE , dependencies ) return dependencies - + def __find_out_used_but_not_exported( self ): used_not_exported = [] exported_ids = set( map( lambda d: id( d ), self.__exported_decls ) ) @@ -97,10 +97,13 @@ if isinstance( depend_on_decl, declarations.class_types ): if depend_on_decl.opaque: continue + if isinstance( decl, declarations.variable_t ): + if not decl.expose_value: + continue if id( depend_on_decl ) not in exported_ids: report = messages.filter_disabled_msgs([messages.W1040], depend_on_decl.disabled_messaged ) if report: - used_not_exported.append( dependency ) + used_not_exported.append( dependency ) return used_not_exported def __group_by_unexposed( self, dependencies ): @@ -118,7 +121,7 @@ for dependency in dependencies: decls.append( os.linesep + ' ' + str( dependency.declaration ) ) return "%s;%s" % ( depend_on_decl, messages.W1040 % ''.join( decls ) ) - + def inform_user( self ): used_not_exported_decls = self.__find_out_used_but_not_exported() groups = self.__group_by_unexposed( used_not_exported_decls ) Added: pyplusplus_dev/unittests/data/unions_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/unions_to_be_exported.hpp (rev 0) +++ pyplusplus_dev/unittests/data/unions_to_be_exported.hpp 2008-08-08 12:18:18 UTC (rev 1386) @@ -0,0 +1,35 @@ +namespace unions{ + +struct data_t{ + union actual_data_t{ + int i; + double d; + }; + actual_data_t data; + + double get_d() const{ return data.d; } + int get_i() const{ return data.i; } + + void set_d( double d ){ data.d = d; } + void set_i( int i ){ data.i = i; } +}; + +} + +namespace anonymous_unions{ + +struct data2_t{ + union{ + int i; + double d; + }; + + double get_d() const{ return d; } + int get_i() const{ return i; } + + void set_d( double _d ){ d = _d; } + void set_i( int _i ){ i = _i; } + +}; + +} Modified: pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp 2008-08-08 12:18:18 UTC (rev 1386) @@ -6,21 +6,21 @@ #ifndef __unnamed_enums_to_be_exported_hpp__ #define __unnamed_enums_to_be_exported_hpp__ -namespace unnamed_enums{ - -class color{ - union{ - struct { - float r,g,b,a; - }; - float val[4]; - }; -}; - -struct{ - int x; -} unnamed_struct_with_mem_var_x; +namespace unnamed_enums{ +struct color{ + union{ + struct { + float r,g,b,a; + }; + float val[4]; + }; +}; + +struct{ + int x; +} unnamed_struct_with_mem_var_x; + } #endif//__unnamed_enums_to_be_exported_hpp__ Modified: pyplusplus_dev/unittests/module_body_tester.py =================================================================== --- pyplusplus_dev/unittests/module_body_tester.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/unittests/module_body_tester.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -10,14 +10,14 @@ class tester_t(fundamental_tester_base.fundamental_tester_base_t): EXTENSION_NAME = 'module_body' - + def __init__( self, *args ): - fundamental_tester_base.fundamental_tester_base_t.__init__( + fundamental_tester_base.fundamental_tester_base_t.__init__( self , tester_t.EXTENSION_NAME , *args ) - def customize(self, mb): + def customize(self, mb): item = mb.class_( 'item_t' ) item.include() item.add_declaration_code( "int get11( const mb::item_t& item ){ return 11;}" ) @@ -31,12 +31,14 @@ mb.build_code_creator( self.EXTENSION_NAME ) - def run_tests(self, module): + mb.add_constants( version='"0.0.0"') + + def run_tests(self, module): self.failUnless( 1 == module.get1() ) self.failUnless( 11 == module.item_t().get11() ) - + self.failUnless( "0.0.0" == module.version ) def create_suite(): - suite = unittest.TestSuite() + suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) return suite @@ -44,4 +46,4 @@ unittest.TextTestRunner(verbosity=2).run( create_suite() ) if __name__ == "__main__": - run_suite() \ No newline at end of file + run_suite() Added: pyplusplus_dev/unittests/unions_tester.py =================================================================== --- pyplusplus_dev/unittests/unions_tester.py (rev 0) +++ pyplusplus_dev/unittests/unions_tester.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -0,0 +1,53 @@ +# Copyright 2004 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 sys +import ctypes +import unittest +import fundamental_tester_base + +class actual_data_t( ctypes.Union ): + _fields_ = [( "i", ctypes.c_int ), ( 'd', ctypes.c_double )] + +#this is compilation test +class tester_t(fundamental_tester_base.fundamental_tester_base_t): + EXTENSION_NAME = 'unions' + + def __init__( self, *args ): + fundamental_tester_base.fundamental_tester_base_t.__init__( + self + , tester_t.EXTENSION_NAME + , *args ) + + def run_tests(self, module): + obj = module.data_t() + actual_data = actual_data_t.from_address( obj.data ) + obj.set_d( 4.0 ) + self.failUnless( actual_data.d == 4.0 ) + obj.set_i( 1977 ) + self.failUnless( actual_data.i == 1977 ) + actual_data.i = 18 + self.failUnless( obj.get_i() == 18 ) + actual_data.d = 12.12 + self.failUnless( obj.get_d() == 12.12 ) + + obj2 = module.data2_t() + obj2.set_d( 4.0 ) + self.failUnless( obj2.d == 4.0 ) + obj2.set_i( 1977 ) + self.failUnless( obj2.i == 1977 ) + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(tester_t)) + return suite + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run( create_suite() ) + +if __name__ == "__main__": + run_suite() Modified: pyplusplus_dev/unittests/unnamed_classes_tester.py =================================================================== --- pyplusplus_dev/unittests/unnamed_classes_tester.py 2008-08-08 10:51:47 UTC (rev 1385) +++ pyplusplus_dev/unittests/unnamed_classes_tester.py 2008-08-08 12:18:18 UTC (rev 1386) @@ -7,22 +7,24 @@ import sys import unittest import fundamental_tester_base -from pyplusplus import code_creators +from pygccxml import declarations +from pyplusplus import code_creators class unnamed_enums_tester_t(fundamental_tester_base.fundamental_tester_base_t): EXTENSION_NAME = 'unnamed_classes' - + def __init__( self, *args ): - fundamental_tester_base.fundamental_tester_base_t.__init__( + fundamental_tester_base.fundamental_tester_base_t.__init__( self , unnamed_enums_tester_t.EXTENSION_NAME , *args ) - def run_tests(self, module): - pass - + def run_tests(self, module): + color = module.color() + r,g,b,a = color.r, color.g, color.b, color.a + def create_suite(): - suite = unittest.TestSuite() + suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(unnamed_enums_tester_t)) return suite @@ -30,4 +32,4 @@ unittest.TextTestRunner(verbosity=2).run( create_suite() ) if __name__ == "__main__": - run_suite() \ No newline at end of file + run_suite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |