[pygccxml-commit] SF.net SVN: pygccxml:[1773] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2009-11-04 22:08:20
|
Revision: 1773 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1773&view=rev Author: roman_yakovenko Date: 2009-11-04 22:08:12 +0000 (Wed, 04 Nov 2009) Log Message: ----------- commit new function transformers from Beno?\195?\174t Leveau Modified Paths: -------------- pyplusplus_dev/docs/history/history.rest pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/transformers.py pyplusplus_dev/unittests/member_variables_tester.py Modified: pyplusplus_dev/docs/history/history.rest =================================================================== --- pyplusplus_dev/docs/history/history.rest 2009-11-04 20:24:32 UTC (rev 1772) +++ pyplusplus_dev/docs/history/history.rest 2009-11-04 22:08:12 UTC (rev 1773) @@ -25,6 +25,7 @@ * Andrei Vermel * Carsten( spom.spom ) * Pertti Kellomäki +* Benoît Leveau ----------- SVN Version @@ -53,6 +54,18 @@ 7. The bug related to transformed virtual function was fixed. Many thanks to Pertti Kellomäki. +8. Thanks to Benoît Leveau, the "Function Transformation" documentation + is much better now. + +9. The following transformers were added: + + * ``inout_static_array`` + * ``input_static_matrix`` + * ``output_static_matrix`` + * ``inout_static_matrix`` + + Many thanks to Benoît Leveau. + ----------- Version 1.0 ----------- Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2009-11-04 20:24:32 UTC (rev 1772) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2009-11-04 22:08:12 UTC (rev 1773) @@ -160,6 +160,11 @@ return '' def _exportable_impl( self ): + if self.transformations: + #It is possible that the function asked for the user attention. + #The user paid attention and created a transformation. + #Py++ should be silent in this case. + return '' if not self.parent.name: return messages.W1057 % str( self ) all_types = [ arg.type for arg in self.arguments ] Modified: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2009-11-04 20:24:32 UTC (rev 1772) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2009-11-04 22:08:12 UTC (rev 1773) @@ -30,7 +30,27 @@ def creator( function ): return transformers.output_static_array_t( function, *args, **keywd ) return creator + +def inout_static_array( *args, **keywd ): + def creator( function ): + return transformers.inout_static_array_t( function, *args, **keywd ) + return creator +def input_static_matrix( *args, **keywd ): + def creator( function ): + return transformers.input_static_matrix_t( function, *args, **keywd ) + return creator + +def output_static_matrix( *args, **keywd ): + def creator( function ): + return transformers.output_static_matrix_t( function, *args, **keywd ) + return creator + +def inout_static_matrix( *args, **keywd ): + def creator( function ): + return transformers.inout_static_matrix_t( function, *args, **keywd ) + return creator + def modify_type( *args, **keywd ): def creator( function ): return transformers.type_modifier_t( function, *args, **keywd ) Modified: pyplusplus_dev/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2009-11-04 20:24:32 UTC (rev 1772) +++ pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2009-11-04 22:08:12 UTC (rev 1773) @@ -165,7 +165,7 @@ def __str__(self): return "input(%s)"%(self.arg.name) -# input_t +# from_address_t class from_address_t(type_modifier_t): """Handles a single input variable. @@ -193,6 +193,7 @@ def __str__(self): return "from_address(%s)"%(self.arg.name) +# inout_t class inout_t(transformer.transformer_t): """Handles a single input/output variable. @@ -261,6 +262,10 @@ _arr2seq = string.Template( 'pyplus_conv::copy_container( $native_array, $native_array + $array_size, pyplus_conv::list_inserter( $pylist ) );' ) +_mat2seq = string.Template( + 'for (int i=0; i<$matrix_size1; ++i) { boost::python::list ${pylist}_i; pyplus_conv::copy_container( $native_matrix[i], $native_matrix[i] + $matrix_size2, pyplus_conv::list_inserter( ${pylist}_i ) ); $pylist.append(${pylist}_i); }' ) + + class input_static_array_t(transformer.transformer_t): """Handles an input array with fixed size. @@ -430,7 +435,378 @@ self.__configure_v_mem_fun_override( controller.override_controller ) self.__configure_v_mem_fun_default( controller.default_controller ) +# inout_static_array_t +class inout_static_array_t(transformer.transformer_t): + """Handles an input/output array with fixed size. + void do_something(double* v) -> v2 = do_something(object v2) + + where v2 is a Python sequence + """ + + def __init__(self, function, arg_ref, size): + """Constructor. + + :param arg_ref: Index of the argument that is an input/output array + :type arg_ref: int + :param size: The fixed size of the input/output array + :type size: int + """ + transformer.transformer_t.__init__( self, function ) + + self.arg = self.get_argument( arg_ref ) + self.arg_index = self.function.arguments.index( self.arg ) + + if not is_ptr_or_array( self.arg.type ): + raise ValueError( '%s\nin order to use "inout_array" transformation, argument %s type must be a array or a pointer (got %s).' ) \ + % ( function, self.arg.name, self.arg.type) + + self.array_size = size + self.array_item_type = declarations.remove_const( declarations.array_item_type( self.arg.type ) ) + + def __str__(self): + return "inout_array(%s,%d)"%( self.arg.name, self.array_size) + + def required_headers( self ): + """Returns list of header files that transformer generated code depends on.""" + return [ code_repository.convenience.file_name ] + + def __configure_sealed(self, controller): + global _seq2arr + global _arr2seq + w_arg = controller.find_wrapper_arg( self.arg.name ) + w_arg.type = declarations.dummy_type_t( "boost::python::object" ) + + # Declare a variable that will hold the C array... + native_array = controller.declare_variable( self.array_item_type + , "native_" + self.arg.name + , '[%d]' % self.array_size ) + + copy_pylist2arr = _seq2arr.substitute( type=self.array_item_type + , pylist=w_arg.name + , array_size=self.array_size + , native_array=native_array ) + + controller.add_pre_call_code( copy_pylist2arr ) + controller.modify_arg_expression( self.arg_index, native_array ) + + # Declare a Python list which will receive the output... + pylist = controller.declare_variable( declarations.dummy_type_t( "boost::python::list" ) + , 'py_' + self.arg.name ) + + copy_arr2pylist = _arr2seq.substitute( native_array=native_array + , array_size=self.array_size + , pylist=pylist ) + controller.add_post_call_code( copy_arr2pylist ) + + #adding the variable to return variables list + controller.return_variable( pylist ) + + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + + def __configure_v_mem_fun_override( self, controller ): + global _arr2seq + pylist = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::list' ) + , 'py_' + self.arg.name ) + + copy_arr2pylist = _arr2seq.substitute( native_array=self.arg.name + , array_size=self.array_size + , pylist=pylist ) + + controller.add_py_pre_call_code( copy_arr2pylist ) + + def configure_mem_fun( self, controller ): + self.__configure_sealed( controller ) + + def configure_free_fun(self, controller ): + self.__configure_sealed( controller ) + + def configure_virtual_mem_fun( self, controller ): + self.__configure_v_mem_fun_override( controller.override_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) + +# input_static_matrix_t +class input_static_matrix_t(transformer.transformer_t): + """Handles an input matrix with fixed size. + + is_identity(double m[3][3]) -> is_identity(object m) + # m must be a sequence of 3 sequences of 3 floats + """ + + def __init__(self, function, arg_ref, size1, size2): + """Constructor. + + :param size1, size2: The fixed size of the input matrix + :type size1, size2: int + """ + transformer.transformer_t.__init__( self, function ) + + self.arg = self.get_argument( arg_ref ) + self.arg_index = self.function.arguments.index( self.arg ) + + if not is_ptr_or_array( self.arg.type ): + raise ValueError( '%s\nin order to use "input_matrix" transformation, argument %s type must be a array or a pointer (got %s).' ) \ + % ( function, self.arg.name, self.arg.type) + + self.matrix_size1 = size1 + self.matrix_size2 = size2 + self.matrix_item_type = declarations.remove_const( declarations.array_item_type( declarations.array_item_type( self.arg.type ) ) ) + + def __str__(self): + return "input_matrix(%s,%d,%d)"%( self.arg.name, self.matrix_size1, self.matrix_size2) + + def required_headers( self ): + """Returns list of header files that transformer generated code depends on.""" + return [ code_repository.convenience.file_name ] + + def __configure_sealed(self, controller): + global _seq2arr + w_arg = controller.find_wrapper_arg( self.arg.name ) + w_arg.type = declarations.dummy_type_t( "boost::python::object" ) + + # Declare a variable that will hold the C matrix... + native_matrix = controller.declare_variable( self.matrix_item_type + , "native_" + self.arg.name + , '[%d][%d]' % (self.matrix_size1, self.matrix_size2) + ) + + pre_call = string.Template('pyplus_conv::ensure_uniform_sequence< $type >( $pylist, $array_size );') + controller.add_pre_call_code(pre_call.substitute(type='boost::python::list', pylist=w_arg.name,array_size=self.matrix_size1)) + + #TODO: may be a better idea is move this loop to the generated code. + for i in range(0,self.matrix_size1): + copy_pylist2arr = _seq2arr.substitute( type=self.matrix_item_type + , pylist=w_arg.name+"["+str(i)+"]" + , array_size=self.matrix_size2 + , native_array=native_matrix+'['+str(i)+']' ) + + controller.add_pre_call_code( copy_pylist2arr ) + + controller.modify_arg_expression( self.arg_index, native_matrix ) + + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + + def __configure_v_mem_fun_override( self, controller ): + global _arr2seq + pylist = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::list' ) + , 'py_' + self.arg.name ) + + #TODO: may be a better idea is move this loop to the generated code. + for i in range(0, self.matrix_size1): + copy_arr2pylist = _arr2seq.substitute( native_array=self.arg.name+'[%d]'%i + , array_size=self.matrix_size2 + , pylist=pylist ) + + controller.add_py_pre_call_code( copy_arr2pylist ) + + def configure_mem_fun( self, controller ): + self.__configure_sealed( controller ) + + def configure_free_fun(self, controller ): + self.__configure_sealed( controller ) + + def configure_virtual_mem_fun( self, controller ): + self.__configure_v_mem_fun_override( controller.override_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) + +# output_static_matrix_t +class output_static_matrix_t(transformer.transformer_t): + """Handles an output matrix with fixed size. + + get_matrix(double m[3][3]) -> m = get_matrix() + # m will be a sequence of 3 sequences of 3 floats + """ + + def __init__(self, function, arg_ref, size1, size2): + """Constructor. + + :param arg_ref: Index of the argument that is an output matrix + :type arg_ref: int + :param size1, size2: The fixed size of the output matrix + :type size1, size2: int + + """ + transformer.transformer_t.__init__( self, function ) + + self.arg = self.get_argument( arg_ref ) + self.arg_index = self.function.arguments.index( self.arg ) + + if not is_ptr_or_array( self.arg.type ): + raise ValueError( '%s\nin order to use "output_matrix" transformation, argument %s type must be a array or a pointer (got %s).' ) \ + % ( function, self.arg.name, self.arg.type) + + self.matrix_size1 = size1 + self.matrix_size2 = size2 + self.matrix_item_type = declarations.remove_const( declarations.array_item_type( declarations.array_item_type( self.arg.type ) ) ) + + def __str__(self): + return "output_matrix(%s,%d,%d)"%( self.arg.name, self.matrix_size1, self.matrix_size2) + + def required_headers( self ): + """Returns list of header files that transformer generated code depends on.""" + return [ code_repository.convenience.file_name ] + + def __configure_sealed(self, controller): + global _mat2seq + #removing arg from the function wrapper definition + controller.remove_wrapper_arg( self.arg.name ) + + # Declare a variable that will hold the C matrix... + native_matrix = controller.declare_variable( self.matrix_item_type + , "native_" + self.arg.name + , '[%d][%d]' % (self.matrix_size1, self.matrix_size2) + ) + #adding just declared variable to the original function call expression + controller.modify_arg_expression( self.arg_index, native_matrix ) + + # Declare a Python list which will receive the output... + pylist = controller.declare_variable( declarations.dummy_type_t( "boost::python::list" ) + , 'py_' + self.arg.name ) + + copy_mat2pylist = _mat2seq.substitute( native_matrix = native_matrix, + matrix_size1=self.matrix_size1, + matrix_size2=self.matrix_size2, + pylist=pylist) + + controller.add_post_call_code( copy_mat2pylist ) + + #adding the variable to return variables list + controller.return_variable( pylist ) + + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + + def __configure_v_mem_fun_override( self, controller ): + global _seq2arr + seq = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::object' ) + , 'py_' + self.arg.name ) + controller.remove_py_arg( self.arg_index ) + tmpl = string.Template( '$seq = pyplus_conv::get_out_argument( $py_result, "$name" );' ) + get_ref_to_seq = tmpl.substiture( seq=seq + , py_result=controller.py_result_variable_name + , name=self.arg.name ) + controller.add_py_post_call_code( get_ref_to_seq ) + + #TODO: may be a better idea is move this loop to the generated code. + for i in range(0, self.matrix_size1): + copy_pylist2arr = _seq2arr.substitute( type=self.matrix_item_type + , pylist=seq + , array_size=self.matrix_size2 + , native_array=self.arg.name+'[%d]'%i ) + controller.add_py_post_call_code( copy_pylist2arr ) + + def configure_mem_fun( self, controller ): + self.__configure_sealed( controller ) + + def configure_free_fun(self, controller ): + self.__configure_sealed( controller ) + + def configure_virtual_mem_fun( self, controller ): + self.__configure_v_mem_fun_override( controller.override_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) + +# inout_static_matrix_t +class inout_static_matrix_t(transformer.transformer_t): + """Handles an input/output matrix with fixed size. + + transpose_matrix(double m[3][3]) -> m = transpose_matrix(object m) + # m must be a sequence of 3 sequences of 3 floats + """ + + def __init__(self, function, arg_ref, size1, size2): + """Constructor. + + :param arg_ref: Index of the argument that is an input/output matrix + :type arg_ref: int + :param size1,size2: The fixed size of the input/output matrix + :type size1,size2: int + """ + transformer.transformer_t.__init__( self, function ) + + self.arg = self.get_argument( arg_ref ) + self.arg_index = self.function.arguments.index( self.arg ) + + if not is_ptr_or_array( self.arg.type ): + raise ValueError( '%s\nin order to use "inout_matrix" transformation, argument %s type must be a array or a pointer (got %s).' ) \ + % ( function, self.arg.name, self.arg.type) + + self.matrix_size1 = size1 + self.matrix_size2 = size2 + self.matrix_item_type = declarations.remove_const( declarations.array_item_type( declarations.array_item_type( self.arg.type ) ) ) + + def __str__(self): + return "inout_matrix(%s,%d,%d)"%( self.arg.name, self.matrix_size1, self.matrix_size2) + + def required_headers( self ): + """Returns list of header files that transformer generated code depends on.""" + return [ code_repository.convenience.file_name ] + + def __configure_sealed(self, controller): + global _seq2arr + global _mat2seq + w_arg = controller.find_wrapper_arg( self.arg.name ) + w_arg.type = declarations.dummy_type_t( "boost::python::object" ) + + # Declare a variable that will hold the C matrix... + native_matrix = controller.declare_variable( self.matrix_item_type + , "native_" + self.arg.name + , '[%d][%d]' % (self.matrix_size1, self.matrix_size2) + ) + + pre_call = string.Template('pyplus_conv::ensure_uniform_sequence< $type >( $pylist, $array_size );') + controller.add_pre_call_code(pre_call.substitute(type='boost::python::list', pylist=w_arg.name,array_size=self.matrix_size1)) + + #TODO: may be a better idea is move this loop to the generated code. + for i in range(0,self.matrix_size1): + copy_pylist2arr = _seq2arr.substitute( type=self.matrix_item_type + , pylist=w_arg.name+"["+str(i)+"]" + , array_size=self.matrix_size2 + , native_array=native_matrix+'['+str(i)+']' ) + + controller.add_pre_call_code( copy_pylist2arr ) + + controller.modify_arg_expression( self.arg_index, native_matrix ) + + pylist = controller.declare_variable( declarations.dummy_type_t( "boost::python::list" ) + , 'py_' + self.arg.name ) + copy_mat2pylist = _mat2seq.substitute( native_matrix = native_matrix, + matrix_size1=self.matrix_size1, + matrix_size2=self.matrix_size2, + pylist=pylist) + + controller.add_post_call_code( copy_mat2pylist ) + + #adding the variable to return variables list + controller.return_variable( pylist ) + + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + + def __configure_v_mem_fun_override( self, controller ): + global _mat2seq + pylist = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::list' ) + , 'py_' + self.arg.name ) + + copy_mat2pylist = _mat2seq.substitute( native_matrix=self.arg.name + , matrix_size1=self.matrix_size1 + , matrix_size2=self.matrix_size2 + , pylist=pylist ) + + controller.add_py_pre_call_code( copy_arr2pylist ) + + def configure_mem_fun( self, controller ): + self.__configure_sealed( controller ) + + def configure_free_fun(self, controller ): + self.__configure_sealed( controller ) + + def configure_virtual_mem_fun( self, controller ): + self.__configure_v_mem_fun_override( controller.override_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) + +# input_c_buffer_t class input_c_buffer_t(transformer.transformer_t): """ handles an input of C buffer: @@ -523,7 +899,6 @@ self.__configure_v_mem_fun_override( controller.override_controller ) self.__configure_v_mem_fun_default( controller.default_controller ) - class transfer_ownership_t(type_modifier_t): """see http://boost.org/libs/python/doc/v2/faq.html#ownership """ Modified: pyplusplus_dev/unittests/member_variables_tester.py =================================================================== --- pyplusplus_dev/unittests/member_variables_tester.py 2009-11-04 20:24:32 UTC (rev 1772) +++ pyplusplus_dev/unittests/member_variables_tester.py 2009-11-04 22:08:12 UTC (rev 1773) @@ -55,23 +55,6 @@ self.failUnless( bf.b == module.get_b( bf ) ) self.failIfNotRaisesAny( lambda: self.set_b( bf, 23 ) ) - array = module.array_t() - self.failUnless( len( array.vars ) == 3 ) - for i in range( len( array.vars ) ): - self.failUnless( array.vars[i].value == -9 ) - self.failUnless( len( array.ivars ) == 10 ) - - ivars = array.ivars - del array #testing call policies - for i in range(20): - for index in range(10): - self.failUnless( ivars[index] == -index ) - - array = module.array_t() - for index in range( len(array.ivars) ): - array.ivars[index] = index * index - self.failUnless( array.get_ivars_item( index ) == index * index ) - tree = module.create_tree() self.failUnless( tree.parent is None ) self.failUnless( tree.data.value == 0 ) @@ -109,6 +92,24 @@ data = data_type.from_address( module.image_t.none_image ) self.failUnless( 1997 == data.contents.value ) + array = module.array_t() + self.failUnless( len( array.ivars ) == 10 ) + + ivars = array.ivars + del array #testing call policies + for i in range(20): + for index in range(10): + self.failUnless( ivars[index] == -index ) + + array = module.array_t() + for index in range( len(array.ivars) ): + array.ivars[index] = index * index + self.failUnless( array.get_ivars_item( index ) == index * index ) + + self.failUnless( len( array.vars ) == 3 ) + for i in range( len( array.vars ) ): + self.failUnless( array.vars[i].value == -9 ) + def create_suite(): suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |