| Trees | Indices | Help | 
 | 
|---|
|  | 
  1  # Copyright 2006 Roman Yakovenko. 
  2  # Distributed under the Boost Software License, Version 1.0. (See 
  3  # accompanying file LICENSE_1_0.txt or copy at 
  4  # http://www.boost.org/LICENSE_1_0.txt) 
  5  # 
  6  # Initial author: Matthias Baas 
  7   
  8  """This module contains the standard argument policy objects. 
  9   
 10  The following policies are available: 
 11   
 12   - L{output_t} 
 13   - L{input_t} 
 14   - L{inout_t} 
 15   - L{input_array_t} 
 16   - L{output_array_t} 
 17   - L{type_modifier_t} 
 18  """ 
 19  import os 
 20  import string 
 21  import transformer 
 22  import controllers 
 23  from pygccxml import declarations 
 24  from pyplusplus import code_repository 
 25   
 26  #TODO: pointers should be checked for NULL 
 27   
 30   
 33   
 35      if declarations.is_pointer( type_ ): 
 36          return declarations.remove_pointer( type_ ) 
 37      elif declarations.is_reference( type_ ): 
 38          return declarations.remove_reference( type_ ) 
 39      else: 
 40          raise TypeError( 'Type should be reference or pointer, got %s.' % type_ ) 
 41   
 42   
 43  # output_t 
 45      """Handles a single output variable. 
 46   
 47      The specified variable is removed from the argument list and is turned 
 48      into a return value. 
 49   
 50      void getValue(int& v) -> v = getValue() 
 51      """ 
 52   
 54          transformer.transformer_t.__init__( self, function ) 
 55          """Constructor. 
 56   
 57          The specified argument must be a reference or a pointer. 
 58   
 59          @param arg_ref: Index of the argument that is an output value (the first arg has index 1). 
 60          @type arg_ref: int 
 61          """ 
 62          self.arg = self.get_argument( arg_ref ) 
 63          self.arg_index = self.function.arguments.index( self.arg ) 
 64   
 65          if not is_ref_or_ptr( self.arg.type ): 
 66              raise ValueError( '%s\nin order to use "output" transformation, argument %s type must be a reference or a pointer (got %s).' ) \ 
 67                    % ( function, self.arg_ref.name, arg.type) 
 68   
 70          return "output(%d)"%(self.arg.name) 
 71   
 73          """Returns list of header files that transformer generated code depends on.""" 
 74          return [ code_repository.convenience.file_name ] 
 75   
 77          #removing arg from the function wrapper definition 
 78          controller.remove_wrapper_arg( self.arg.name ) 
 79          #declaring new variable, which will keep result 
 80          var_name = controller.declare_variable( remove_ref_or_ptr( self.arg.type ), self.arg.name ) 
 81          #adding just declared variable to the original function call expression 
 82          controller.modify_arg_expression( self.arg_index, var_name ) 
 83          #adding the variable to return variables list 
 84          controller.return_variable( var_name ) 
 85   
 87          self.__configure_sealed( controller ) 
 88   
 90          controller.remove_py_arg( self.arg_index ) 
 91          tmpl = string.Template( 
 92              '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) 
 93          store_py_result_in_arg = tmpl.substitute( name=self.arg.name 
 94                                                    , type=remove_ref_or_ptr( self.arg.type ).decl_string 
 95                                                    , py_result=controller.py_result_variable.name ) 
 96          controller.add_py_post_call_code( store_py_result_in_arg ) 
 97   
 99          self.__configure_sealed( controller ) 
100   
102          self.__configure_sealed( controller ) 
103   
105          self.__configure_v_mem_fun_default( controller.default_controller ) 
106          self.__configure_v_mem_fun_override( controller.override_controller ) 
107   
108  # input_t 
110      """Change/modify type of the argument. 
111   
112      Right now compiler should be able to use implicit conversion 
113      """ 
114   
116          """Constructor. 
117   
118          modifier is callable, which take the type of the argument and should return 
119          new type 
120          """ 
121          transformer.transformer_t.__init__( self, function ) 
122          self.arg = self.get_argument( arg_ref ) 
123          self.arg_index = self.function.arguments.index( self.arg ) 
124          self.modifier = modifier 
125   
127          return "type_modifier(%s)" % self.arg.name 
128   
130          w_arg = controller.find_wrapper_arg( self.arg.name ) 
131          w_arg.type = self.modifier( self.arg.type ) 
132          if not declarations.is_convertible( w_arg.type, self.arg.type ): 
133              casting_code = 'reinterpret_cast< %s >( %s )' % ( self.arg.type, w_arg.name ) 
134              controller.modify_arg_expression(self.arg_index, casting_code) 
135   
137          self.__configure_sealed( controller ) 
138   
140          self.__configure_sealed( controller ) 
141   
143          self.__configure_sealed( controller ) 
144   
147   
151   
152  # input_t 
154      """Handles a single input variable. 
155   
156      The reference on the specified variable is removed. 
157   
158      void setValue(int& v) -> setValue(v) 
159      """ 
160   
162          """Constructor. 
163   
164          The specified argument must be a reference or a pointer. 
165   
166          @param idx: Index of the argument that is an output value (the first arg has index 1). 
167          @type idx: int 
168          """ 
169          type_modifier_t.__init__( self, function, arg_ref, remove_ref_or_ptr ) 
170   
171          if not is_ref_or_ptr( self.arg.type ): 
172              raise ValueError( '%s\nin order to use "input" transformation, argument %s type must be a reference or a pointer (got %s).' ) \ 
173                    % ( function, self.arg_ref.name, arg.type) 
174   
176          return "input(%s)"%(self.arg.name) 
177   
178  # input_t 
180      """Handles a single input variable. 
181   
182      Replaces the actual argument type with some integral type, so you 
183      can use ctypes package. 
184   
185      void do_smth(int** image) -> do_smth(unsigned int addressof_image) 
186   
187      """ 
188   
190          """Constructor. 
191   
192          The specified argument must be a reference or a pointer. 
193   
194          @param idx: Index of the argument that is an output value (the first arg has index 1). 
195          @type idx: int 
196          """ 
197          modifier = lambda type_: declarations.FUNDAMENTAL_TYPES[ 'unsigned int' ] 
198          type_modifier_t.__init__( self, function, arg_ref, modifier ) 
199   
200          if not is_ptr_or_array( self.arg.type ): 
201              raise ValueError( '%s\nin order to use "from_address_t" transformation, argument %s type must be a pointer or a array (got %s).' ) \ 
202                    % ( function, self.arg_ref.name, arg.type) 
203   
205          return "from_address(%s)"%(self.arg.name) 
206   
207  # inout_t 
209      """Handles a single input/output variable. 
210   
211      void foo(int& v) -> v = foo(v) 
212      """ 
213   
215          """Constructor. 
216   
217          The specified argument must be a reference or a pointer. 
218   
219          @param idx: Index of the argument that is an in/out value (the first arg has index 1). 
220          @type idx: int 
221          """ 
222          transformer.transformer_t.__init__( self, function ) 
223          self.arg = self.get_argument( arg_ref ) 
224          self.arg_index = self.function.arguments.index( self.arg ) 
225   
226          if not is_ref_or_ptr( self.arg.type ): 
227              raise ValueError( '%s\nin order to use "inout" transformation, argument %s type must be a reference or a pointer (got %s).' ) \ 
228                    % ( function, self.arg_ref.name, arg.type) 
229   
231          return "inout(%s)"%(self.arg.name) 
232   
234          w_arg = controller.find_wrapper_arg( self.arg.name ) 
235          w_arg.type = remove_ref_or_ptr( self.arg.type ) 
236          #adding the variable to return variables list 
237          controller.return_variable( w_arg.name ) 
238   
240          self.__configure_sealed( controller ) 
241   
243          tmpl = string.Template( 
244              '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) 
245          store_py_result_in_arg = tmpl.substitute( name=self.arg.name 
246                                                    , type=remove_ref_or_ptr( self.arg.type ).decl_string 
247                                                    , py_result=controller.py_result_variable.name ) 
248          controller.add_py_post_call_code( store_py_result_in_arg ) 
249   
251          self.__configure_sealed( controller ) 
252   
254          self.__configure_sealed( controller ) 
255   
257          self.__configure_v_mem_fun_override( controller.override_controller ) 
258          self.__configure_v_mem_fun_default( controller.default_controller ) 
259   
261          """Returns list of header files that transformer generated code depends on.""" 
262          return [ code_repository.convenience.file_name ] 
263   
264   
265  _seq2arr = string.Template( os.linesep.join([ 
266                'pyplus_conv::ensure_uniform_sequence< $type >( $pylist, $array_size );' 
267              , 'pyplus_conv::copy_sequence( $pylist, pyplus_conv::array_inserter( $native_array, $array_size ) );'])) 
268   
269  _seq2vector = string.Template( os.linesep.join([ 
270                   'pyplus_conv::ensure_uniform_sequence< $type >( $pylist );' 
271                 , 'pyplus_conv::copy_sequence( $pylist, std::back_inserter( $native_array), boost::type< $type >() );'])) 
272   
273  _arr2seq = string.Template( 
274              'pyplus_conv::copy_container( $native_array, $native_array + $array_size, pyplus_conv::list_inserter( $pylist ) );' ) 
275   
277      """Handles an input array with fixed size. 
278   
279      void setVec3(double* v) ->  setVec3(object v) 
280      # v must be a sequence of 3 floats 
281      """ 
282   
284          """Constructor. 
285   
286          @param size: The fixed size of the input array 
287          @type size: int 
288          """ 
289          transformer.transformer_t.__init__( self, function ) 
290   
291          self.arg = self.get_argument( arg_ref ) 
292          self.arg_index = self.function.arguments.index( self.arg ) 
293   
294          if not is_ptr_or_array( self.arg.type ): 
295              raise ValueError( '%s\nin order to use "input_array" transformation, argument %s type must be a array or a pointer (got %s).' ) \ 
296                    % ( function, self.arg.name, self.arg.type) 
297   
298          self.array_size = size 
299          self.array_item_type = declarations.remove_const( declarations.array_item_type( self.arg.type ) ) 
300   
303   
305          """Returns list of header files that transformer generated code depends on.""" 
306          return [ code_repository.convenience.file_name ] 
307   
309          global _seq2arr 
310          w_arg = controller.find_wrapper_arg( self.arg.name ) 
311          w_arg.type = declarations.dummy_type_t( "boost::python::object" ) 
312   
313          # Declare a variable that will hold the C array... 
314          native_array = controller.declare_variable( self.array_item_type 
315                                                      , "native_" + self.arg.name 
316                                                      , '[%d]' % self.array_size ) 
317   
318          copy_pylist2arr = _seq2arr.substitute( type=self.array_item_type 
319                                                  , pylist=w_arg.name 
320                                                  , array_size=self.array_size 
321                                                  , native_array=native_array ) 
322   
323          controller.add_pre_call_code( copy_pylist2arr ) 
324   
325          controller.modify_arg_expression( self.arg_index, native_array ) 
326   
328          self.__configure_sealed( controller ) 
329   
331          global _arr2seq 
332          pylist = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::list' ) 
333                                                   , 'py_' + self.arg.name ) 
334   
335          copy_arr2pylist = _arr2seq.substitute( native_array=self.arg.name 
336                                                  , array_size=self.array_size 
337                                                  , pylist=pylist ) 
338   
339          controller.add_py_pre_call_code( copy_arr2pylist ) 
340   
342          self.__configure_sealed( controller ) 
343   
345          self.__configure_sealed( controller ) 
346   
348          self.__configure_v_mem_fun_override( controller.override_controller ) 
349          self.__configure_v_mem_fun_default( controller.default_controller ) 
350   
351   
352  # s - static 
354      """Handles an output array of a fixed size. 
355   
356      void getVec3(double* v) -> v = getVec3() 
357      # v will be a list with 3 floats 
358      """ 
359   
361          """Constructor. 
362   
363          @param idx: Index of the argument that is an output array (the first arg has index 1). 
364          @type idx: int 
365          @param size: The fixed size of the output array 
366          @type size: int 
367          """ 
368          transformer.transformer_t.__init__( self, function ) 
369          self.arg = self.get_argument( arg_ref ) 
370          self.arg_index = self.function.arguments.index( self.arg ) 
371   
372          if not is_ptr_or_array( self.arg.type ): 
373              raise ValueError( '%s\nin order to use "input_array" transformation, argument %s type must be a array or a pointer (got %s).' ) \ 
374                    % ( function, self.arg.name, self.arg.type) 
375   
376          self.array_size = size 
377          self.array_item_type = declarations.array_item_type( self.arg.type ) 
378   
381   
383          """Returns list of header files that transformer generated code depends on.""" 
384          return [ code_repository.convenience.file_name ] 
385   
387          global _arr2seq 
388          #removing arg from the function wrapper definition 
389          controller.remove_wrapper_arg( self.arg.name ) 
390   
391          # Declare a variable that will hold the C array... 
392          native_array = controller.declare_variable( self.array_item_type 
393                                                      , "native_" + self.arg.name 
394                                                      , '[%d]' % self.array_size ) 
395   
396          #adding just declared variable to the original function call expression 
397          controller.modify_arg_expression( self.arg_index, native_array ) 
398   
399          # Declare a Python list which will receive the output... 
400          pylist = controller.declare_variable( declarations.dummy_type_t( "boost::python::list" ) 
401                                                , 'py_' + self.arg.name ) 
402   
403          copy_arr2pylist = _arr2seq.substitute( native_array=native_array 
404                                                 , array_size=self.array_size 
405                                                 , pylist=pylist ) 
406   
407          controller.add_post_call_code( copy_arr2pylist ) 
408   
409          #adding the variable to return variables list 
410          controller.return_variable( pylist ) 
411   
413          self.__configure_sealed( controller ) 
414   
416          global _seq2arr 
417          seq = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::object' ) 
418                                                , 'py_' + self.arg.name ) 
419          controller.remove_py_arg( self.arg_index ) 
420          tmpl = string.Template( '$seq = pyplus_conv::get_out_argument( $py_result, "$name" );' ) 
421          get_ref_to_seq = tmpl.substitute( seq=seq 
422                                            , py_result=controller.py_result_variable.name 
423                                            , name=self.arg.name ) 
424          controller.add_py_post_call_code( get_ref_to_seq ) 
425   
426          copy_pylist2arr = _seq2arr.substitute( type=self.array_item_type 
427                                                 , pylist=seq 
428                                                 , array_size=self.array_size 
429                                                 , native_array=self.arg.name ) 
430          controller.add_py_post_call_code( copy_pylist2arr ) 
431   
433          self.__configure_sealed( controller ) 
434   
436          self.__configure_sealed( controller ) 
437   
439          self.__configure_v_mem_fun_override( controller.override_controller ) 
440          self.__configure_v_mem_fun_default( controller.default_controller ) 
441   
442   
444      """Handles an input of C buffere: 
445   
446      void write( byte *buffer, int size ) -> void write( python sequence ) 
447      """ 
448   
450          """Constructor. 
451   
452          @param buffer_arg_ref: "reference" to the buffer argument 
453          @param buffer_arg_ref: "reference" to argument, which holds buffer size 
454          """ 
455          transformer.transformer_t.__init__( self, function ) 
456   
457          self.buffer_arg = self.get_argument( buffer_arg_ref ) 
458          self.buffer_arg_index = self.function.arguments.index( self.buffer_arg ) 
459   
460          self.size_arg = self.get_argument( size_arg_ref ) 
461          self.size_arg_index = self.function.arguments.index( self.size_arg ) 
462   
463          if not is_ptr_or_array( self.buffer_arg.type ): 
464              raise ValueError( '%s\nin order to use "input_c_buffer" transformation, "buffer" argument %s type must be a array or a pointer (got %s).' ) \ 
465                    % ( function, self.buffer_arg.name, self.buffer_arg.type) 
466   
467          if not declarations.is_integral( self.size_arg.type ): 
468              raise ValueError( '%s\nin order to use "input_c_buffer" transformation, "size" argument %s type must be an integral type (got %s).' ) \ 
469                    % ( function, self.size_arg.name, self.size_arg.type) 
470   
471          self.buffer_item_type = declarations.remove_const( declarations.array_item_type( self.buffer_arg.type ) ) 
472   
474          return "input_c_buffer(buffer arg=%s, size arg=%s)" \ 
475                 % ( self.buffer_arg.name, self.size_arg.name) 
476   
478          """Returns list of header files that transformer generated code depends on.""" 
479          return [ code_repository.convenience.file_name, '<vector>', '<iterator>' ] 
480   
482          global _seq2arr 
483          w_buffer_arg = controller.find_wrapper_arg( self.buffer_arg.name ) 
484          w_buffer_arg.type = declarations.dummy_type_t( "boost::python::object" ) 
485   
486          controller.remove_wrapper_arg( self.size_arg.name ) 
487   
488          size_var = controller.declare_variable( 
489                            declarations.remove_const( self.size_arg.type ) 
490                          , self.size_arg.name 
491                          , ' = boost::python::len(%s)' % w_buffer_arg.name ) 
492   
493          # Declare a variable that will hold the C array... 
494          buffer_var = controller.declare_variable( 
495                            declarations.dummy_type_t( "std::vector< %s >" % self.buffer_item_type.decl_string ) 
496                          , "native_" + self.buffer_arg.name ) 
497   
498          controller.add_pre_call_code( '%s.reserve( %s );' % ( buffer_var, size_var ) ) 
499   
500          copy_pylist2arr = _seq2vector.substitute( type=self.buffer_item_type 
501                                                    , pylist=w_buffer_arg.name 
502                                                    , native_array=buffer_var ) 
503   
504          controller.add_pre_call_code( copy_pylist2arr ) 
505   
506          controller.modify_arg_expression( self.buffer_arg_index, '&%s[0]' % buffer_var ) 
507          controller.modify_arg_expression( self.size_arg_index, '%s' % size_var ) 
508   
510          self.__configure_sealed( controller ) 
511   
514          #global _arr2seq 
515          #pylist = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::list' ) 
516                                                   #, 'py_' + self.arg.name ) 
517   
518          #copy_arr2pylist = _arr2seq.substitute( native_array=self.arg.name 
519                                                  #, array_size=self.array_size 
520                                                  #, pylist=pylist ) 
521   
522          #controller.add_py_pre_call_code( copy_arr2pylist ) 
523   
525          self.__configure_sealed( controller ) 
526   
528          self.__configure_sealed( controller ) 
529   
531          self.__configure_v_mem_fun_override( controller.override_controller ) 
532          self.__configure_v_mem_fun_default( controller.default_controller ) 
533   
534   
536      """see http://boost.org/libs/python/doc/v2/faq.html#ownership 
537      """ 
539          """Constructor.""" 
540          transformer.transformer_t.__init__( self, function ) 
541          self.arg = self.get_argument( arg_ref ) 
542          self.arg_index = self.function.arguments.index( self.arg ) 
543          if not declarations.is_pointer( self.arg.type ): 
544              raise ValueError( '%s\nin order to use "transfer ownership" transformation, argument %s type must be a pointer (got %s).' ) \ 
545                    % ( function, self.arg_ref.name, arg.type) 
546   
548          return "transfer_ownership(%s)" % self.arg.name 
549   
551          w_arg = controller.find_wrapper_arg( self.arg.name ) 
552          naked_type = declarations.remove_pointer( self.arg.type ) 
553          naked_type = declarations.remove_declarated( naked_type ) 
554          w_arg.type = declarations.dummy_type_t( 'std::auto_ptr< %s >' % naked_type.decl_string ) 
555          controller.modify_arg_expression(self.arg_index, w_arg.name + '.release()' ) 
556   
558          self.__configure_sealed( controller ) 
559   
561          self.__configure_sealed( controller ) 
562   
564          self.__configure_sealed( controller ) 
565   
568   
569  #TODO: FT for constructor 
570      #~ def configure_constructor( self, controller ): 
571          #~ self.__configure_sealed( controller ) 
572   
576   
| Trees | Indices | Help | 
 | 
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 20 08:51:36 2008 | http://epydoc.sourceforge.net |