[pygccxml-commit] SF.net SVN: pygccxml:[1378] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2008-07-23 20:40:51
|
Revision: 1378 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1378&view=rev Author: roman_yakovenko Date: 2008-07-23 20:40:56 +0000 (Wed, 23 Jul 2008) Log Message: ----------- adding from_address function transformation Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/transformers.py Added Paths: ----------- pyplusplus_dev/unittests/data/ft_from_address_to_be_exported.hpp pyplusplus_dev/unittests/ft_from_address_tester.py Modified: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2008-07-23 19:17:20 UTC (rev 1377) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2008-07-23 20:40:56 UTC (rev 1378) @@ -59,3 +59,10 @@ def creator( function ): return transformers.transfer_ownership_t( function, *args, **keywd ) return creator + +def from_address( *args, **keywd ): + def creator( function ): + return transformers.from_address_t( function, *args, **keywd ) + return creator + + Modified: pyplusplus_dev/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2008-07-23 19:17:20 UTC (rev 1377) +++ pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2008-07-23 20:40:56 UTC (rev 1378) @@ -38,8 +38,8 @@ return declarations.remove_reference( type_ ) else: raise TypeError( 'Type should be reference or pointer, got %s.' % type_ ) - + # output_t class output_t( transformer.transformer_t ): """Handles a single output variable. @@ -61,7 +61,7 @@ """ self.arg = self.get_argument( arg_ref ) self.arg_index = self.function.arguments.index( self.arg ) - + if not is_ref_or_ptr( self.arg.type ): raise ValueError( '%s\nin order to use "output" transformation, argument %s type must be a reference or a pointer (got %s).' ) \ % ( function, self.arg_ref.name, arg.type) @@ -79,13 +79,13 @@ #declaring new variable, which will keep result var_name = controller.declare_variable( remove_ref_or_ptr( self.arg.type ), self.arg.name ) #adding just declared variable to the original function call expression - controller.modify_arg_expression( self.arg_index, var_name ) + controller.modify_arg_expression( self.arg_index, var_name ) #adding the variable to return variables list controller.return_variable( var_name ) def __configure_v_mem_fun_default( self, controller ): self.__configure_sealed( controller ) - + def __configure_v_mem_fun_override( self, controller ): controller.remove_py_arg( self.arg_index ) tmpl = string.Template( @@ -97,10 +97,10 @@ 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_default( controller.default_controller ) self.__configure_v_mem_fun_override( controller.override_controller ) @@ -108,14 +108,14 @@ # input_t class type_modifier_t(transformer.transformer_t): """Change/modify type of the argument. - + Right now compiler should be able to use implicit conversion """ def __init__(self, function, arg_ref, modifier): """Constructor. - modifier is callable, which take the type of the argument and should return + modifier is callable, which take the type of the argument and should return new type """ transformer.transformer_t.__init__( self, function ) @@ -132,23 +132,23 @@ if not declarations.is_convertible( w_arg.type, self.arg.type ): casting_code = 'reinterpret_cast< %s >( %s )' % ( self.arg.type, w_arg.name ) controller.modify_arg_expression(self.arg_index, casting_code) - + def __configure_v_mem_fun_default( self, controller ): self.__configure_sealed( controller ) 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_default( controller.default_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) def required_headers( self ): """Returns list of header files that transformer generated code depends on.""" return [] - + # input_t class input_t(type_modifier_t): """Handles a single input variable. @@ -175,6 +175,35 @@ def __str__(self): return "input(%s)"%(self.arg.name) +# input_t +class from_address_t(type_modifier_t): + """Handles a single input variable. + + Replaces the actual argument type with some integral type, so you + can use ctypes package. + + void do_smth(int** image) -> do_smth(unsigned int addressof_image) + + """ + + def __init__(self, function, arg_ref): + """Constructor. + + The specified argument must be a reference or a pointer. + + @param idx: Index of the argument that is an output value (the first arg has index 1). + @type idx: int + """ + modifier = lambda type_: declarations.FUNDAMENTAL_TYPES[ 'unsigned int' ] + type_modifier_t.__init__( self, function, arg_ref, modifier ) + + if not is_ptr_or_array( self.arg.type ): + raise ValueError( '%s\nin order to use "from_address_t" transformation, argument %s type must be a pointer or a array (got %s).' ) \ + % ( function, self.arg_ref.name, arg.type) + + def __str__(self): + return "from_address(%s)"%(self.arg.name) + # inout_t class inout_t(transformer.transformer_t): """Handles a single input/output variable. @@ -193,7 +222,7 @@ 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_ref_or_ptr( self.arg.type ): raise ValueError( '%s\nin order to use "inout" transformation, argument %s type must be a reference or a pointer (got %s).' ) \ % ( function, self.arg_ref.name, arg.type) @@ -206,10 +235,10 @@ w_arg.type = remove_ref_or_ptr( self.arg.type ) #adding the variable to return variables list controller.return_variable( w_arg.name ) - + def __configure_v_mem_fun_default( self, controller ): self.__configure_sealed( controller ) - + def __configure_v_mem_fun_override( self, controller ): tmpl = string.Template( '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) @@ -220,7 +249,7 @@ def configure_mem_fun( self, controller ): self.__configure_sealed( controller ) - + def configure_free_fun(self, controller ): self.__configure_sealed( controller ) @@ -241,7 +270,7 @@ 'pyplus_conv::ensure_uniform_sequence< $type >( $pylist );' , 'pyplus_conv::copy_sequence( $pylist, std::back_inserter( $native_array), boost::type< $type >() );'])) -_arr2seq = string.Template( +_arr2seq = string.Template( 'pyplus_conv::copy_container( $native_array, $native_array + $array_size, pyplus_conv::list_inserter( $pylist ) );' ) class input_static_array_t(transformer.transformer_t): @@ -258,10 +287,10 @@ @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 "input_array" transformation, argument %s type must be a array or a pointer (got %s).' ) \ % ( function, self.arg.name, self.arg.type) @@ -285,41 +314,41 @@ 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 ) + controller.modify_arg_expression( self.arg_index, native_array ) + 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 ) - + # s - static class output_static_array_t(transformer.transformer_t): """Handles an output array of a fixed size. @@ -365,16 +394,16 @@ , '[%d]' % self.array_size ) #adding just declared variable to the original function call expression - controller.modify_arg_expression( self.arg_index, native_array ) + 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 @@ -393,16 +422,16 @@ , py_result=controller.py_result_variable.name , name=self.arg.name ) controller.add_py_post_call_code( get_ref_to_seq ) - + copy_pylist2arr = _seq2arr.substitute( type=self.array_item_type , pylist=seq , array_size=self.array_size , native_array=self.arg.name ) 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 ) @@ -420,11 +449,11 @@ def __init__(self, function, buffer_arg_ref, size_arg_ref): """Constructor. - @param buffer_arg_ref: "reference" to the buffer argument + @param buffer_arg_ref: "reference" to the buffer argument @param buffer_arg_ref: "reference" to argument, which holds buffer size """ transformer.transformer_t.__init__( self, function ) - + self.buffer_arg = self.get_argument( buffer_arg_ref ) self.buffer_arg_index = self.function.arguments.index( self.buffer_arg ) @@ -453,56 +482,56 @@ global _seq2arr w_buffer_arg = controller.find_wrapper_arg( self.buffer_arg.name ) w_buffer_arg.type = declarations.dummy_type_t( "boost::python::object" ) - + controller.remove_wrapper_arg( self.size_arg.name ) - size_var = controller.declare_variable( + size_var = controller.declare_variable( declarations.remove_const( self.size_arg.type ) , self.size_arg.name , ' = boost::python::len(%s)' % w_buffer_arg.name ) - + # Declare a variable that will hold the C array... - buffer_var = controller.declare_variable( + buffer_var = controller.declare_variable( declarations.dummy_type_t( "std::vector< %s >" % self.buffer_item_type.decl_string ) , "native_" + self.buffer_arg.name ) controller.add_pre_call_code( '%s.reserve( %s );' % ( buffer_var, size_var ) ) - + copy_pylist2arr = _seq2vector.substitute( type=self.buffer_item_type , pylist=w_buffer_arg.name , native_array=buffer_var ) - + controller.add_pre_call_code( copy_pylist2arr ) - - controller.modify_arg_expression( self.buffer_arg_index, '&%s[0]' % buffer_var ) - controller.modify_arg_expression( self.size_arg_index, '%s' % size_var ) + controller.modify_arg_expression( self.buffer_arg_index, '&%s[0]' % buffer_var ) + controller.modify_arg_expression( self.size_arg_index, '%s' % size_var ) + def __configure_v_mem_fun_default( self, controller ): self.__configure_sealed( controller ) - + def __configure_v_mem_fun_override( self, controller ): raise NotImplementedError() #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 ) - + class transfer_ownership_t(type_modifier_t): """see http://boost.org/libs/python/doc/v2/faq.html#ownership """ @@ -524,13 +553,13 @@ naked_type = declarations.remove_declarated( naked_type ) w_arg.type = declarations.dummy_type_t( 'std::auto_ptr< %s >' % naked_type.decl_string ) controller.modify_arg_expression(self.arg_index, w_arg.name + '.release()' ) - + def __configure_v_mem_fun_default( self, controller ): self.__configure_sealed( controller ) def configure_mem_fun( self, controller ): self.__configure_sealed( controller ) - + def configure_free_fun(self, controller ): self.__configure_sealed( controller ) @@ -540,7 +569,7 @@ #TODO: FT for constructor #~ def configure_constructor( self, controller ): #~ self.__configure_sealed( controller ) - + def required_headers( self ): """Returns list of header files that transformer generated code depends on.""" return [] Added: pyplusplus_dev/unittests/data/ft_from_address_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/ft_from_address_to_be_exported.hpp (rev 0) +++ pyplusplus_dev/unittests/data/ft_from_address_to_be_exported.hpp 2008-07-23 20:40:56 UTC (rev 1378) @@ -0,0 +1,25 @@ +// 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) + +#ifndef __ft_from_address_to_be_exported_hpp__ +#define __ft_from_address_to_be_exported_hpp__ + +#include <stdexcept> + +inline unsigned long +sum_matrix( unsigned int** matrix, unsigned int rows, unsigned int columns ){ + if( !matrix ){ + throw std::runtime_error( "matrix is null" ); + } + unsigned long result = 0; + for( unsigned int r = 0; r < rows; ++r ){ + for( unsigned int c = 0; c < columns; ++c ){ + result += matrix[r][c]; + } + } + return result; +} + +#endif//__ft_from_address_to_be_exported_hpp__ Added: pyplusplus_dev/unittests/ft_from_address_tester.py =================================================================== --- pyplusplus_dev/unittests/ft_from_address_tester.py (rev 0) +++ pyplusplus_dev/unittests/ft_from_address_tester.py 2008-07-23 20:40:56 UTC (rev 1378) @@ -0,0 +1,58 @@ +# 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 math +import ctypes +import unittest +import fundamental_tester_base +from pygccxml import declarations +from pyplusplus import function_transformers as ft +from pyplusplus.module_builder import call_policies + + +class tester_t(fundamental_tester_base.fundamental_tester_base_t): + EXTENSION_NAME = 'ft_from_address' + + def __init__( self, *args ): + fundamental_tester_base.fundamental_tester_base_t.__init__( + self + , tester_t.EXTENSION_NAME + , *args ) + + def customize( self, mb ): + + mb.global_ns.calldefs().create_with_signature = True + mb.calldef( 'sum_matrix' ).add_transformation( ft.from_address(0) ) + + def run_tests(self, module): + rows = 1 + columns = 1 + matrix_type = ctypes.c_uint * columns * rows + print matrix_type + sum = 0 + counter = 0 + matrix = matrix_type() + for r in range( rows ): + for c in range( columns ): + matrix[r][c] = counter + sum += counter + counter += 1 + print 'matrix filled' + result = module.sum_matrix( ctypes.addressof( matrix ), rows, columns ) + print 'result: ', result + print 'sum : ', sum + +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() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |