Package pyplusplus :: Package code_creators :: Module member_variable

Source Code for Module pyplusplus.code_creators.member_variable

  1  # Copyright 2004-2008 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  import os 
  7  import algorithm 
  8  import code_creator 
  9  import declaration_based 
 10  from pyplusplus import code_repository 
 11  from pyplusplus.decl_wrappers import call_policies 
 12  from pyplusplus.decl_wrappers import python_traits 
 13  import registration_based 
 14  from pygccxml import declarations 
15 16 -class member_variable_base_t( registration_based.registration_based_t 17 , declaration_based.declaration_based_t ):
18 """ 19 Base class for all member variables code creators. Mainly exists to 20 simplify file writers algorithms. 21 """ 22
23 - def __init__(self, variable, wrapper=None ):
27
28 - def _get_wrapper( self ):
29 return self._wrapper
30 - def _set_wrapper( self, new_wrapper ):
31 self._wrapper = new_wrapper
32 wrapper = property( _get_wrapper, _set_wrapper ) 33
34 - def _get_system_headers_impl( self ):
41
42 -class member_variable_t( member_variable_base_t ):
43 """ 44 Creates boost.python code that exposes member variable. 45 """
46 - def __init__(self, variable, wrapper=None ):
48 49 #> On Wednesday, 19. April 2006 23:05, Ralf W. Grosse-Kunstleve wrote: 50 #> .add_property("p", make_function(&A::get_p, return_value_policy<reference_existing_object>()))
51 - def _generate_for_pointer( self ):
52 doc = '' #static property does not support documentation 53 if self.declaration.type_qualifiers.has_static: 54 add_property = 'add_static_property' 55 else: 56 if self.documentation: 57 doc = self.documentation 58 add_property = 'add_property' 59 answer = [ add_property ] 60 answer.append( '( ' ) 61 answer.append('"%s"' % self.alias) 62 answer.append( self.PARAM_SEPARATOR ) 63 64 #according to David Abrahams: 65 #http://mail.python.org/pipermail/c++-sig/2003-January/003276.html 66 call_pol = call_policies.return_internal_reference().create( self ) 67 make_function = algorithm.create_identifier( self, '::boost::python::make_function' ) 68 69 answer.append( '%(mk_func)s( (%(getter_type)s)(&%(wfname)s), %(call_pol)s )' 70 % { 'mk_func' : make_function 71 , 'getter_type' : self.wrapper.getter_type 72 , 'wfname' : self.wrapper.getter_full_name 73 , 'call_pol' : call_pol } ) 74 75 #don't generate setter method, right now I don't know how to do it. 76 if self.wrapper.has_setter: 77 answer.append( self.PARAM_SEPARATOR ) 78 call_pol = '' 79 if not self.declaration.type_qualifiers.has_static: 80 call_pol = ", " + call_policies.with_custodian_and_ward_postcall( 1, 2 ).create(self) 81 answer.append( '%(mk_func)s( (%(setter_type)s)(&%(wfname)s)%(call_pol)s )' 82 % { 'mk_func' : make_function 83 , 'setter_type' : self.wrapper.setter_type 84 , 'wfname' : self.wrapper.setter_full_name 85 , 'call_pol' : call_pol } ) 86 if doc: 87 answer.append( self.PARAM_SEPARATOR ) 88 answer.append( doc ) 89 answer.append( ' ) ' ) 90 91 code = ''.join( answer ) 92 if len( code ) <= self.LINE_LENGTH: 93 return code 94 else: 95 for i in range( len( answer ) ): 96 if answer[i] == self.PARAM_SEPARATOR: 97 answer[i] = os.linesep + self.indent( self.indent( self.indent( answer[i] ) ) ) 98 return ''.join( answer )
99
100 - def _generate_for_none_pointer( self ):
101 tmpl = None 102 if self.declaration.type_qualifiers.has_static: 103 tmpl = '%(access)s( "%(alias)s", %(name)s%(doc)s )' 104 else: 105 tmpl = '%(access)s( "%(alias)s", &%(name)s%(doc)s )' 106 107 access = 'def_readwrite' 108 if self.declaration.is_read_only: 109 access = 'def_readonly' 110 doc = '' 111 if self.documentation: 112 doc = ', %s' % self.documentation 113 result = tmpl % { 114 'access' : access 115 , 'alias' : self.alias 116 , 'name' : self.decl_identifier 117 , 'doc' : doc } 118 119 return result
120
121 - def _generate_using_functions( self ):
122 doc = '' 123 add_property = '' 124 make_getter = algorithm.create_identifier( self, '::boost::python::make_getter') 125 make_setter = algorithm.create_identifier( self, '::boost::python::make_setter') 126 if self.declaration.type_qualifiers.has_static: 127 add_property = 'add_static_property' 128 else: 129 if self.documentation: 130 doc = self.documentation 131 add_property = 'add_property' 132 add_property_args = [ '"%s"' % self.alias ] 133 getter_code = declarations.call_invocation.join( 134 make_getter 135 , [ '&' + self.decl_identifier 136 , self.declaration.getter_call_policies.create( self ) ] 137 , os.linesep + self.indent( self.PARAM_SEPARATOR, 6) ) 138 139 add_property_args.append( getter_code ) 140 if not self.declaration.is_read_only: 141 setter_code = '' 142 setter_args = [ '&' + self.decl_identifier ] 143 if self.declaration.setter_call_policies \ 144 and not self.declaration.setter_call_policies.is_default(): 145 setter_args.append( self.declaration.setter_call_policies.create( self ) ) 146 setter_code = declarations.call_invocation.join( 147 make_setter 148 , setter_args 149 , os.linesep + self.indent( self.PARAM_SEPARATOR, 6) ) 150 add_property_args.append( setter_code) 151 if doc: 152 add_property_args.append( doc ) 153 return declarations.call_invocation.join( 154 add_property 155 , add_property_args 156 , os.linesep + self.indent( self.PARAM_SEPARATOR, 4 ) )
157
158 - def _create_impl( self ):
159 if declarations.is_pointer( self.declaration.type ): 160 return self._generate_for_pointer() 161 elif self.declaration.apply_smart_ptr_wa or self.declaration.use_make_functions: 162 return self._generate_using_functions() 163 else: 164 return self._generate_for_none_pointer()
165
166 -class member_variable_wrapper_t( code_creator.code_creator_t 167 , declaration_based.declaration_based_t ):
168 """ 169 Creates C++ code that creates accessor for pointer class variables 170 """ 171 #TODO: give user a way to set call policies 172 # treat void* pointer 173 indent = code_creator.code_creator_t.indent 174 MV_GET_TEMPLATE = os.linesep.join([ 175 'static %(type)s get_%(name)s(%(cls_type)s inst ){' 176 , indent( 'return inst.%(name)s;' ) 177 , '}' 178 , '' 179 ]) 180 181 MV_STATIC_GET_TEMPLATE = os.linesep.join([ 182 'static %(type)s get_%(name)s(){' 183 , indent( 'return %(cls_type)s::%(name)s;' ) 184 , '}' 185 , '' 186 ]) 187 188 MV_SET_TEMPLATE = os.linesep.join([ 189 'static void set_%(name)s( %(cls_type)s inst, %(type)s new_value ){ ' 190 , indent( 'inst.%(name)s = new_value;' ) 191 , '}' 192 , '' 193 ]) 194 195 MV_STATIC_SET_TEMPLATE = os.linesep.join([ 196 'static void set_%(name)s( %(type)s new_value ){ ' 197 , indent( '%(cls_type)s::%(name)s = new_value;' ) 198 , '}' 199 , '' 200 ]) 201
202 - def __init__(self, variable ):
205
206 - def _get_getter_full_name(self):
207 return self.parent.full_name + '::' + 'get_' + self.declaration.name
208 getter_full_name = property( _get_getter_full_name ) 209
210 - def inst_arg_type( self, has_const ):
216
217 - def _get_getter_type(self):
227 getter_type = property( _get_getter_type ) 228
229 - def _get_setter_full_name(self):
230 return self.parent.full_name + '::' + 'set_' + self.declaration.name
231 setter_full_name = property(_get_setter_full_name) 232
233 - def _get_setter_type(self):
243 setter_type = property( _get_setter_type ) 244
245 - def _get_has_setter( self ):
246 return not declarations.is_const( self.declaration.type )
247 has_setter = property( _get_has_setter ) 248
249 - def _create_impl(self):
250 answer = [] 251 if self.declaration.type_qualifiers.has_static: 252 substitutions = { 253 'type' : self.declaration.type.decl_string 254 , 'name' : self.declaration.name 255 , 'cls_type' : declarations.full_name( self.declaration.parent ) 256 } 257 answer.append( self.MV_STATIC_GET_TEMPLATE % substitutions) 258 if self.has_setter: 259 answer.append( self.MV_STATIC_SET_TEMPLATE % substitutions ) 260 else: 261 answer.append( self.MV_GET_TEMPLATE % { 262 'type' : self.declaration.type.decl_string 263 , 'name' : self.declaration.name 264 , 'cls_type' : self.inst_arg_type( has_const=True ) }) 265 if self.has_setter: 266 answer.append( self.MV_SET_TEMPLATE % { 267 'type' : self.declaration.type.decl_string 268 , 'name' : self.declaration.name 269 , 'cls_type' : self.inst_arg_type( has_const=False ) }) 270 return os.linesep.join( answer )
271
272 - def _get_system_headers_impl( self ):
273 return []
274
275 -class bit_field_t( member_variable_base_t ):
276 """ 277 Creates boost.python code that exposes bit fields member variables 278 """
279 - def __init__(self, variable, wrapper ):
281
282 - def _create_impl( self ):
283 doc = '' 284 if self.declaration.type_qualifiers.has_static: 285 add_property = 'add_static_property' 286 else: 287 if self.documentation: 288 doc = self.documentation 289 add_property = 'add_property' 290 answer = [ add_property ] 291 answer.append( '( ' ) 292 answer.append('"%s"' % self.alias) 293 answer.append( self.PARAM_SEPARATOR ) 294 answer.append( '(%s)(&%s)' 295 % ( self.wrapper.getter_type, self.wrapper.getter_full_name ) ) 296 297 if self.wrapper.has_setter: 298 answer.append( self.PARAM_SEPARATOR ) 299 answer.append( '(%s)(&%s)' 300 % ( self.wrapper.setter_type, self.wrapper.setter_full_name ) ) 301 if doc: 302 answer.append( self.PARAM_SEPARATOR ) 303 answer.append( doc ) 304 answer.append( ' ) ' ) 305 306 code = ''.join( answer ) 307 if len( code ) <= self.LINE_LENGTH: 308 return code 309 else: 310 for i in range( len( answer ) ): 311 if answer[i] == self.PARAM_SEPARATOR: 312 answer[i] = os.linesep + self.indent( self.indent( self.indent( answer[i] ) ) ) 313 return ''.join( answer )
314
315 -class bit_field_wrapper_t( code_creator.code_creator_t 316 , declaration_based.declaration_based_t ):
317 """ 318 Creates C++ code that creates accessor for bit fields 319 """ 320 321 indent = code_creator.code_creator_t.indent 322 BF_GET_TEMPLATE = os.linesep.join([ 323 '%(type)s get_%(name)s() const {' 324 , indent( 'return %(name)s;' ) 325 , '}' 326 , '' 327 ]) 328 329 BF_SET_TEMPLATE = os.linesep.join([ 330 'void set_%(name)s( %(type)s new_value ){ ' 331 , indent( '%(name)s = new_value;' ) 332 , '}' 333 , '' 334 ]) 335
336 - def __init__(self, variable ):
339
340 - def _get_getter_full_name(self):
341 return self.parent.full_name + '::' + 'get_' + self.declaration.name
342 getter_full_name = property( _get_getter_full_name ) 343
344 - def _get_getter_type(self):
345 return declarations.member_function_type_t.create_decl_string( 346 return_type=self.declaration.type 347 , class_decl_string=self.parent.full_name 348 , arguments_types=[] 349 , has_const=True 350 , with_defaults=False)
351 getter_type = property( _get_getter_type ) 352
353 - def _get_setter_full_name(self):
354 return self.parent.full_name + '::' + 'set_' + self.declaration.name
355 setter_full_name = property(_get_setter_full_name) 356
357 - def _get_setter_type(self):
358 return declarations.member_function_type_t.create_decl_string( 359 return_type=declarations.void_t() 360 , class_decl_string=self.parent.full_name 361 , arguments_types=[self.declaration.type] 362 , has_const=False 363 , with_defaults=False)
364 setter_type = property( _get_setter_type ) 365
366 - def _get_has_setter( self ):
367 return not declarations.is_const( self.declaration.type )
368 has_setter = property( _get_has_setter ) 369
370 - def _create_impl(self):
371 answer = [] 372 substitutions = dict( type=self.declaration.type.decl_string 373 , name=self.declaration.name ) 374 answer.append( self.BF_GET_TEMPLATE % substitutions ) 375 if self.has_setter: 376 answer.append( self.BF_SET_TEMPLATE % substitutions ) 377 return os.linesep.join( answer )
378
379 - def _get_system_headers_impl( self ):
380 return []
381
382 -class array_mv_t( member_variable_base_t ):
383 """ 384 Creates boost.python code that exposes array member variable. 385 """
386 - def __init__(self, variable, wrapper ):
389
390 - def _create_body( self ):
391 answer = [] 392 answer.append( 'typedef %s;' % self.wrapper.wrapper_creator_type.create_typedef( 'array_wrapper_creator' ) ) 393 answer.append( os.linesep * 2 ) 394 395 doc = '' 396 if self.declaration.type_qualifiers.has_static: 397 answer.append( self.parent.class_var_name + '.add_static_property' ) 398 else: 399 if self.documentation: 400 doc = self.documentation 401 answer.append( self.parent.class_var_name + '.add_property' ) 402 answer.append( '( ' ) 403 answer.append('"%s"' % self.declaration.name ) 404 answer.append( os.linesep + self.indent( self.PARAM_SEPARATOR ) ) 405 temp = [ algorithm.create_identifier( self, "::boost::python::make_function" ) ] 406 temp.append( '( ' ) 407 temp.append( 'array_wrapper_creator(&%s)' % self.wrapper.wrapper_creator_full_name ) 408 if not self.declaration.type_qualifiers.has_static: 409 temp.append( os.linesep + self.indent( self.PARAM_SEPARATOR, 6 ) ) 410 temp.append( call_policies.with_custodian_and_ward_postcall( 0, 1 ).create(self) ) 411 temp.append( ' )' ) 412 answer.append( ''.join( temp ) ) 413 if doc: 414 answer.append( os.linesep ) 415 answer.append( self.PARAM_SEPARATOR ) 416 answer.append( doc ) 417 answer.append( ' );' ) 418 return ''.join( answer )
419
420 - def _create_impl( self ):
421 answer = [] 422 answer.append( '{ //%s, type=%s' % ( self.declaration, self.declaration.type ) ) 423 answer.append( os.linesep * 2 ) 424 answer.append( self.indent( self._create_body() ) ) 425 answer.append( os.linesep ) 426 answer.append( '}' ) 427 return ''.join( answer )
428
429 - def _get_system_headers_impl( self ):
430 return []
431
432 433 #TODO: generated fucntion should be static and take instance of the wrapped class 434 #as first argument. 435 -class array_mv_wrapper_t( code_creator.code_creator_t 436 , declaration_based.declaration_based_t ):
437 """ 438 Creates C++ code that register array class. 439 """ 440
441 - def __init__(self, variable ):
444 445 @property
446 - def wrapper_type( self ):
447 tmpl = "%(namespace)s::%(constness)sarray_1_t< %(item_type)s, %(array_size)d>" 448 449 constness = '' 450 if declarations.is_const( self.declaration.type ): 451 constness = 'const_' 452 result = tmpl % { 453 'namespace' : code_repository.array_1.namespace 454 , 'constness' : constness 455 , 'item_type' : declarations.array_item_type( self.declaration.type ).decl_string 456 , 'array_size': declarations.array_size( self.declaration.type ) 457 } 458 return declarations.dummy_type_t( result )
459 460 @property
461 - def wrapped_class_type( self ):
462 wrapped_cls_type = declarations.declarated_t( self.declaration.parent ) 463 if declarations.is_const( self.declaration.type ): 464 wrapped_cls_type = declarations.const_t( wrapped_cls_type ) 465 return declarations.reference_t( wrapped_cls_type )
466 467 @property
468 - def wrapper_creator_type(self):
472 473 @property
474 - def wrapper_creator_name(self):
475 return '_'.join( ['pyplusplus', self.declaration.name, 'wrapper'] )
476 477 @property
479 return '::'.join( [self.parent.full_name, self.wrapper_creator_name] )
480
481 - def _create_impl( self ):
482 tmpl = os.linesep.join([ 483 "static %(wrapper_type)s" 484 , "%(wrapper_creator_name)s( %(wrapped_class_type)s inst ){" 485 , self.indent( "return %(wrapper_type)s( inst.%(mem_var_ref)s );" ) 486 , "}" 487 ]) 488 return tmpl % { 489 'wrapper_type' : self.wrapper_type.decl_string 490 , 'wrapper_creator_name' : self.wrapper_creator_name 491 , 'wrapped_class_type' : self.wrapped_class_type.decl_string 492 , 'mem_var_ref' : self.declaration.name 493 }
494
495 - def _get_system_headers_impl( self ):
497
498 499 -class mem_var_ref_t( member_variable_base_t ):
500 """ 501 Creates C++ code that creates accessor for class member variable, that has type reference. 502 """
503 - def __init__(self, variable, wrapper ):
504 member_variable_base_t.__init__( self, variable=variable, wrapper=wrapper ) 505 self.param_sep = os.linesep + self.indent( self.PARAM_SEPARATOR, 2 ) 506 self.works_on_instance = False
507
508 - def _create_getter( self ):
509 answer = ['def'] 510 answer.append( '( ' ) 511 answer.append( '"get_%s"' % self.alias) 512 answer.append( self.param_sep ) 513 answer.append( '(%s)(&%s)' 514 % ( self.wrapper.getter_type.decl_string, self.wrapper.getter_full_name ) ) 515 if self.declaration.getter_call_policies: 516 if not self.declaration.getter_call_policies.is_default(): 517 answer.append( self.param_sep ) 518 answer.append( self.declaration.getter_call_policies.create( self ) ) 519 else: 520 answer.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) 521 if self.documentation: 522 answer.append( self.param_sep ) 523 answer.append( self.documentation ) 524 answer.append( ' )' ) 525 return ''.join( answer )
526
527 - def _create_setter( self ):
528 answer = ['def'] 529 answer.append( '( ' ) 530 answer.append( '"set_%s"' % self.alias) 531 answer.append( self.param_sep ) 532 answer.append( '(%s)(&%s)' 533 % ( self.wrapper.setter_type.decl_string, self.wrapper.setter_full_name ) ) 534 if self.declaration.setter_call_policies: 535 if not self.declaration.setter_call_policies.is_default(): 536 answer.append( self.param_sep ) 537 answer.append( self.declaration.setter_call_policies.create( self ) ) 538 else: 539 answer.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) 540 answer.append( ' )' ) 541 return ''.join( answer )
542
543 - def _create_impl( self ):
544 #TODO: fix me, should not force class scope usage 545 answer = [] 546 class_var_name = self.parent.class_var_name 547 answer.append( "%s.%s;" % (class_var_name, self._create_getter() ) ) 548 if self.wrapper.has_setter: 549 answer.append( os.linesep ) 550 answer.append( "%s.%s;" % (class_var_name, self._create_setter() ) ) 551 return ''.join( answer )
552
553 -class mem_var_ref_wrapper_t( code_creator.code_creator_t 554 , declaration_based.declaration_based_t ):
555 """ 556 Creates C++ code that creates accessor for class member variable, that has type reference. 557 """ 558 559 indent = code_creator.code_creator_t.indent 560 GET_TEMPLATE = os.linesep.join([ 561 'static %(type)s get_%(name)s( %(class_type)s& inst ) {' 562 , indent( 'return inst.%(name)s;' ) 563 , '}' 564 , '' 565 ]) 566 567 SET_TEMPLATE = os.linesep.join([ 568 'static void set_%(name)s( %(class_type)s& inst, %(type)s new_value ){ ' 569 , indent( 'inst.%(name)s = new_value;' ) 570 , '}' 571 , '' 572 ]) 573
574 - def __init__(self, variable ):
577
578 - def _get_getter_full_name(self):
579 return self.parent.full_name + '::' + 'get_' + self.declaration.name
580 getter_full_name = property( _get_getter_full_name ) 581
582 - def _get_class_inst_type( self ):
584
585 - def _get_exported_var_type( self ):
586 type_ = declarations.remove_reference( self.declaration.type ) 587 type_ = declarations.remove_const( type_ ) 588 if python_traits.is_immutable( type_ ): 589 return type_ 590 else: 591 return self.declaration.type
592
593 - def _get_getter_type(self):
594 return declarations.free_function_type_t( 595 return_type=self._get_exported_var_type() 596 , arguments_types=[ declarations.reference_t( self._get_class_inst_type() ) ] )
597 getter_type = property( _get_getter_type ) 598
599 - def _get_setter_full_name(self):
600 return self.parent.full_name + '::' + 'set_' + self.declaration.name
601 setter_full_name = property(_get_setter_full_name) 602
603 - def _get_setter_type(self):
604 return declarations.free_function_type_t( 605 return_type=declarations.void_t() 606 , arguments_types=[ declarations.reference_t( self._get_class_inst_type() ) 607 , self._get_exported_var_type() ] )
608 setter_type = property( _get_setter_type ) 609
610 - def _get_has_setter( self ):
611 if declarations.is_const( declarations.remove_reference( self.declaration.type ) ): 612 return False 613 elif python_traits.is_immutable( self._get_exported_var_type() ): 614 return True 615 else: 616 pass 617 618 no_ref = declarations.remove_reference( self.declaration.type ) 619 no_const = declarations.remove_const( no_ref ) 620 base_type = declarations.remove_alias( no_const ) 621 if not isinstance( base_type, declarations.declarated_t ): 622 return True #TODO ???? 623 decl = base_type.declaration 624 if decl.is_abstract: 625 return False 626 if declarations.has_destructor( decl ) and not declarations.has_public_destructor( decl ): 627 return False 628 if not declarations.has_copy_constructor(decl): 629 return False 630 return True
631 has_setter = property( _get_has_setter ) 632
633 - def _create_impl(self):
634 answer = [] 635 cls_type = algorithm.create_identifier( self, self.declaration.parent.decl_string ) 636 637 substitutions = dict( type=self._get_exported_var_type().decl_string 638 , class_type=cls_type 639 , name=self.declaration.name ) 640 answer.append( self.GET_TEMPLATE % substitutions ) 641 if self.has_setter: 642 answer.append( self.SET_TEMPLATE % substitutions ) 643 return os.linesep.join( answer )
644
645 - def _get_system_headers_impl( self ):
646 return []
647
648 -class member_variable_addressof_t( member_variable_base_t ):
649 """ 650 Creates boost.python code that exposes address of member variable. 651 652 This functionality is pretty powerful if you use it with "ctypes" - 653 standard package. 654 655 """
656 - def __init__(self, variable, wrapper=None ):
658
659 - def _create_m_var( self ):
660 answer = [ 'add_property' ] 661 answer.append( '( ' ) 662 answer.append('"%s"' % self.alias) 663 answer.append( self.PARAM_SEPARATOR ) 664 answer.append( 'pyplus_conv::make_addressof_getter(&%s)' 665 % self.decl_identifier ) 666 if self.documentation: 667 answer.append( self.PARAM_SEPARATOR ) 668 answer.append( self.documentation ) 669 answer.append( ' ) ' ) 670 return ''.join( answer )
671
672 - def _create_s_var( self ):
673 return 'def( %(def_visitor)s("%(name)s", %(var)s) )' \ 674 % { 'def_visitor' : 'pyplus_conv::register_addressof_static_var' 675 , 'name' : self.alias 676 , 'var' : self.decl_identifier }
677 678
679 - def _create_impl( self ):
680 if self.declaration.type_qualifiers.has_static: 681 return self._create_s_var() 682 else: 683 return self._create_m_var()
684 - def _get_system_headers_impl( self ):
686