Trees | Indices | Help |
|
---|
|
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 declarations15 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 """ 224124 registration_based.registration_based_t.__init__( self ) 25 declaration_based.declaration_based_t.__init__( self, declaration=variable) 26 self._wrapper = wrapper27 32 wrapper = property( _get_wrapper, _set_wrapper ) 3335 files = [] 36 if self.declaration.getter_call_policies: 37 files.append( self.declaration.getter_call_policies.header_file ) 38 if self.declaration.setter_call_policies: 39 files.append( self.declaration.setter_call_policies.header_file ) 40 return files43 """ 44 Creates boost.python code that exposes member variable. 45 """ 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>()))16552 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 )99101 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 result120122 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 ) )157159 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()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 ]) 201274203 code_creator.code_creator_t.__init__( self ) 204 declaration_based.declaration_based_t.__init__( self, declaration=variable)205 208 getter_full_name = property( _get_getter_full_name ) 209211 inst_arg_type = declarations.declarated_t( self.declaration.parent ) 212 if has_const: 213 inst_arg_type = declarations.const_t(inst_arg_type) 214 inst_arg_type = declarations.reference_t(inst_arg_type) 215 return inst_arg_type216218 if self.declaration.type_qualifiers.has_static: 219 arguments_types=[] 220 else: 221 arguments_types=[ self.inst_arg_type(True) ] 222 223 return declarations.free_function_type_t.create_decl_string( 224 return_type=self.declaration.type 225 , arguments_types=arguments_types 226 , with_defaults=False)227 getter_type = property( _get_getter_type ) 228 231 setter_full_name = property(_get_setter_full_name) 232234 if self.declaration.type_qualifiers.has_static: 235 arguments_types=[ self.declaration.type ] 236 else: 237 arguments_types=[ self.inst_arg_type(False), self.declaration.type ] 238 239 return declarations.free_function_type_t.create_decl_string( 240 return_type=declarations.void_t() 241 , arguments_types=arguments_types 242 , with_defaults=False)243 setter_type = property( _get_setter_type ) 244 247 has_setter = property( _get_has_setter ) 248250 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 )271276 """ 277 Creates boost.python code that exposes bit fields member variables 278 """ 281314283 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 )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 ]) 335381337 code_creator.code_creator_t.__init__( self ) 338 declaration_based.declaration_based_t.__init__( self, declaration=variable)339 342 getter_full_name = property( _get_getter_full_name ) 343345 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 355 setter_full_name = property(_get_setter_full_name) 356358 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 368 has_setter = property( _get_has_setter ) 369371 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 )378383 """ 384 Creates boost.python code that exposes array member variable. 385 """431387 member_variable_base_t.__init__( self, variable=variable, wrapper=wrapper ) 388 self.works_on_instance = False389391 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 )419421 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 )428432 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 """ 440497442 code_creator.code_creator_t.__init__( self ) 443 declaration_based.declaration_based_t.__init__( self, declaration=variable)444 445 @property447 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 @property462 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 @property469 return declarations.free_function_type_t( 470 return_type=self.wrapper_type 471 , arguments_types=[self.wrapped_class_type] )472 473 @property 476 477 @property 480482 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 }494500 """ 501 Creates C++ code that creates accessor for class member variable, that has type reference. 502 """552504 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 = False507509 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 )526528 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 )542544 #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 )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 ]) 573647575 code_creator.code_creator_t.__init__( self ) 576 declaration_based.declaration_based_t.__init__( self, declaration=variable)577 580 getter_full_name = property( _get_getter_full_name ) 581 584586 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.type592594 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 601 setter_full_name = property(_get_setter_full_name) 602604 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 ) 609611 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 True631 has_setter = property( _get_has_setter ) 632634 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 )644649 """ 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 """ 658686660 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 )671673 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 678680 if self.declaration.type_qualifiers.has_static: 681 return self._create_s_var() 682 else: 683 return self._create_m_var()
Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Mon Oct 20 08:51:24 2008 | http://epydoc.sourceforge.net |