Revision: 46
Author: roman_yakovenko
Date: 2006-05-01 22:17:01 -0700 (Mon, 01 May 2006)
ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=46&view=rev
Log Message:
-----------
adding exportable functionality
adding overridable property
Virtual functions, that returns [const]reference, could not be overriden
from Python. The reason is simple: in boost::python::override::operator(...)
result of marshaling (Python 2 C++) is saved on stack, after function
exit, the result will be reference to no where - access violetion.
For example see temporal variable tester.
Modified Paths:
--------------
pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py
Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py
===================================================================
--- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-05-02 05:04:56 UTC (rev 45)
+++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-05-02 05:17:01 UTC (rev 46)
@@ -22,6 +22,7 @@
self._use_keywords = True
self._use_default_arguments = True
self._create_with_signature = False
+ self._overridable = None
def get_call_policies(self):
return self._call_policies
@@ -30,13 +31,13 @@
call_policies = property( get_call_policies, set_call_policies )
def _get_use_keywords(self):
- return self._use_keywords
+ return self._use_keywords and bool( self.arguments )
def _set_use_keywords(self, use_keywords):
self._use_keywords = use_keywords
use_keywords = property( _get_use_keywords, _set_use_keywords )
def _get_create_with_signature(self):
- return self._create_with_signature
+ return self._create_with_signature or bool( self.overloads )
def _set_create_with_signature(self, create_with_signature):
self._create_with_signature = create_with_signature
create_with_signature = property( _get_create_with_signature, _set_create_with_signature)
@@ -67,7 +68,52 @@
else:
pass
- def readme( self ):
+ def get_overridable( self ):
+ """
+ Virtual functions, that returns const reference, could not be overriden
+ from Python. The reason is simple: in boost::python::override::operator(...)
+ result of marshaling (Python 2 C++) is saved on stack, after function
+ exit, the result will be reference to no where - access violetion.
+ For example see temporal variable tester
+ """
+ if None is self._overridable:
+ if isinstance( self, declarations.member_calldef_t ) \
+ and self.virtuality != declarations.VIRTUALITY_TYPES.NOT_VIRTUAL \
+ and declarations.is_reference( self.return_type ):
+ self._overridable = False
+ else:
+ self._overridable = True
+ return self._overridable
+
+ def set_overridable( self, overridable ):
+ self._overridable = overridable
+
+ overridable = property( get_overridable, set_overridable
+ , doc = get_overridable.__doc__ )
+
+ def _exportable_impl( self ):
+ #see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr
+ if len( self.arguments ) > 10:
+ return "boost.python can not expose function with more then 10 arguments. ( impl details: boost.tuple is limited to 10 args )."
+ all_types = [ arg.type for arg in self.arguments ]
+ all_types.append( self.return_type )
+ for some_type in all_types:
+ units = declarations.decompose_type( some_type )
+ ptr2functions = filter( lambda unit: isinstance( unit, declarations.calldef_type_t )
+ , units )
+ if ptr2functions:
+ return "boost.python can not expose function, which takes as argument/returns pointer to function." \
+ + " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information."
+ #Function that take as agrument some instance of non public class
+ #will not be exported. Same to the return variable
+ if isinstance( units[-1], declarations.declarated_t ):
+ dtype = units[-1]
+ if isinstance( dtype.declaration.parent, declarations.class_t ):
+ if dtype.declaration not in dtype.declaration.parent.public_members:
+ return "pyplusplus can not expose fuction that takes as argument/returns instance of non public class. Generated code will not compile."
+ return ''
+
+ def _readme_impl( self ):
def suspicious_type( type_ ):
if not declarations.is_reference( self.return_type ):
return False
@@ -83,23 +129,57 @@
+ 'non-const reference to C++ fundamental type - ' \
+ 'function could not be called from Python.'
msg.append( tmpl % ( str( self ), arg.name, index ) )
+
+ if False == self.overridable:
+ msg.append( self.get_overridable.__doc__ )
return msg
-
+
class member_function_t( declarations.member_function_t, calldef_t ):
def __init__(self, *arguments, **keywords):
declarations.member_function_t.__init__( self, *arguments, **keywords )
calldef_t.__init__( self )
-
+
class constructor_t( declarations.constructor_t, calldef_t ):
def __init__(self, *arguments, **keywords):
declarations.constructor_t.__init__( self, *arguments, **keywords )
calldef_t.__init__( self )
+
+ def _exportable_impl( self ):
+ if self.is_artificial:
+ return 'pyplusplus does not exports compiler generated constructors'
+ return ''
+
class destructor_t( declarations.destructor_t, calldef_t ):
def __init__(self, *arguments, **keywords):
declarations.destructor_t.__init__( self, *arguments, **keywords )
calldef_t.__init__( self )
-
+
+class operators_helper:
+
+ inplace = [ '+=', '-=', '*=', '/=', '%=', '>>=', '<<=', '&=', '^=', '|=' ]
+ comparison = [ '==', '!=', '<', '>', '<=', '>=' ]
+ non_member = [ '+', '-', '*', '/', '%', '&', '^', '|' ] #'>>', '<<', not implemented
+ unary = [ '!', '~', '+', '-' ]
+
+ all = inplace + comparison + non_member + unary
+
+ def is_supported( oper ):
+ if oper.symbol == '*' and len( oper.arguments ) == 0:
+ #dereference does not make sense
+ return False
+ return oper.symbol in operators_helper.all
+ is_supported = staticmethod( is_supported )
+
+ def exportable( oper ):
+ if isinstance( oper, declarations.member_operator_t ) and oper.symbol in ( '()', '[]' ):
+ return ''
+ if not operators_helper.is_supported( oper ):
+ #see http://www.boost.org/libs/python/doc/v2/operators.html#introduction
+ return 'operator %s is not supported. Please take a look on http://www.boost.org/libs/python/doc/v2/operators.html#introduction.'
+ return ''
+ exportable = staticmethod( exportable )
+
class member_operator_t( declarations.member_operator_t, calldef_t ):
def __init__(self, *arguments, **keywords):
declarations.member_operator_t.__init__( self, *arguments, **keywords )
@@ -117,11 +197,72 @@
return alias
alias = property( _get_alias, decl_wrapper.decl_wrapper_t._set_alias )
+ def _exportable_impl( self ):
+ return operators_helper.exportable( self )
+
+
class casting_operator_t( declarations.casting_operator_t, calldef_t ):
+
+ def prepare_special_cases():
+ """
+ Creates a map of special cases ( aliases ) for casting operator.
+ """
+ special_cases = {}
+ const_t = declarations.const_t
+ pointer_t = declarations.pointer_t
+ for type_ in declarations.FUNDAMENTAL_TYPES.values():
+ alias = None
+ if declarations.is_same( type_, declarations.bool_t() ):
+ alias = '__int__'
+ elif declarations.is_integral( type_ ):
+ if 'long' in type_.decl_string:
+ alias = '__long__'
+ else:
+ alias = '__int__'
+ elif declarations.is_floating_point( type_ ):
+ alias = '__float__'
+ else:
+ continue #void
+ if alias:
+ special_cases[ type_ ] = alias
+ special_cases[ const_t( type_ ) ] = alias
+ special_cases[ pointer_t( const_t( declarations.char_t() ) ) ] = '__str__'
+ std_string = '::std::basic_string<char,std::char_traits<char>,std::allocator<char> >'
+ std_wstring = '::std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >'
+ special_cases[ std_string ] = '__str__'
+ special_cases[ std_wstring ] = '__str__'
+ special_cases[ '::std::string' ] = '__str__'
+ special_cases[ '::std::wstring' ] = '__str__'
+
+ #TODO: add
+ # std::complex<SomeType> some type should be converted to double
+ return special_cases
+
+ SPECIAL_CASES = prepare_special_cases()
+ #casting_member_operator_t.prepare_special_cases()
+
def __init__(self, *arguments, **keywords):
declarations.casting_operator_t.__init__( self, *arguments, **keywords )
calldef_t.__init__( self )
+ def _get_alias( self):
+ if not self._alias or self.name == super( member_operator_t, self )._get_alias():
+ return_type = declarations.remove_alias( self.return_type )
+ decl_string = return_type.decl_string
+ for type_, alias in self.SPECIAL_CASES.items():
+ if isinstance( type_, declarations.type_t ):
+ if declarations.is_same( return_type, type_ ):
+ self._alias = alias
+ break
+ else:
+ if decl_string == type_:
+ self._alias = alias
+ break
+ else:
+ self._alias = 'as_' + self._generate_valid_name(self.return_type.decl_string)
+ return self._alias
+ alias = property( _get_alias, decl_wrapper.decl_wrapper_t._set_alias )
+
class free_function_t( declarations.free_function_t, calldef_t ):
def __init__(self, *arguments, **keywords):
declarations.free_function_t.__init__( self, *arguments, **keywords )
@@ -131,3 +272,6 @@
def __init__(self, *arguments, **keywords):
declarations.free_operator_t.__init__( self, *arguments, **keywords )
calldef_t.__init__( self )
+
+ def _exportable_impl( self ):
+ return operators_helper.exportable( self )
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|