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