Thread: [pygccxml-commit] SF.net SVN: pygccxml: [527] pyplusplus_dev/pyplusplus/function_transformers /subs
Brought to you by:
mbaas,
roman_yakovenko
From: <mb...@us...> - 2006-09-06 13:58:37
|
Revision: 527 http://svn.sourceforge.net/pygccxml/?rev=527&view=rev Author: mbaas Date: 2006-09-06 06:58:33 -0700 (Wed, 06 Sep 2006) Log Message: ----------- Added the method py_result_expr() + a couple of smaller additions/fixes Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-06 13:57:07 UTC (rev 526) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-06 13:58:33 UTC (rev 527) @@ -126,6 +126,8 @@ - RESULT_VAR_ASSIGNMENT: "<varname> = " or empty + - RESULT_TYPE: The type of the result variable + - CALL_FUNC_NAME: The name of the function that should be invoked (self?). - INPUT_PARAMS: The values or variables that will be passed to $FUNC_NAME, @@ -154,7 +156,7 @@ @type virtual_func: L{code_manager_t} @group Methods called by the user of the class: append_code_block, subst_wrapper, subst_virtual, get_includes - @group Methods called by the arg policies: remove_arg, insert_arg, require_include + @group Methods called by the function transformers: remove_arg, insert_arg, py_result_expr, require_include @author: Matthias Baas """ @@ -195,7 +197,8 @@ ret_type = None else: ret_type = decl.return_type - self.wrapper_func.result_var = self.wrapper_func.declare_local("result", str(ret_type)) + self.wrapper_func.result_type = str(ret_type) + self.wrapper_func.result_var = self.wrapper_func.declare_local("result", self.wrapper_func.result_type) self.wrapper_func.result_exprs = [self.wrapper_func.result_var] self.virtual_func.ret_type = ret_type @@ -212,6 +215,11 @@ self.wrapper_func.CALL_FUNC_NAME = decl.name self.wrapper_func.input_params = map(lambda a: a.name, decl.arguments) + # The offset that is added to the index in insert_arg() + # This index is either 0 for free functions or 1 for member functions + # because the "self" argument is not a regular argument. + self._insert_arg_idx_offset = 0 + # Check if we're dealing with a member function... clsdecl = self._class_decl(decl) if clsdecl!=None: @@ -219,6 +227,7 @@ selfarg = declarations.argument_t(selfname, "%s&"%clsdecl.name) self.wrapper_func.arg_list.insert(0, selfarg) self.wrapper_func.CALL_FUNC_NAME = "%s.%s"%(selfname, self.wrapper_func.CALL_FUNC_NAME) + self._insert_arg_idx_offset = 1 # Argument index map # Original argument index ---> Input arg index (indices are 0-based!) @@ -258,7 +267,8 @@ # Create a variable that will hold the result of the Python call # inside the virtual function. if len(self.wrapper_func.result_exprs)>0: - self.virtual_func.result_var = self.virtual_func.declare_local("pyresult", "boost::python::object") + self.virtual_func.result_type = "boost::python::object" + self.virtual_func.result_var = self.virtual_func.declare_local("pyresult", self.virtual_func.result_type) # self.virtual_func.result_expr = self.virtual_func.result_var self.wrapper_func.init_variables() @@ -312,7 +322,7 @@ if idx is 0 and the function has no return type). You must not modify this object as it may still be in use on the virtual function. - @rtype: argument_t + @rtype: L{argument_t<pygccxml.declarations.calldef.argument_t>} """ if self._funcs_initialized: raise ValueError, "remove_arg() may only be called before function initialization." @@ -351,7 +361,7 @@ return arg # insert_arg - def insert_arg(self, idx, arg): + def insert_arg(self, idx, arg, inputexpr): """Insert a new argument into the argument list of the wrapper function. This function is supposed to be called by function transformer @@ -360,7 +370,9 @@ @param idx: New argument index (may be negative) @type idx: int @param arg: New argument object - @type arg: argument_t + @type arg: L{argument_t<pygccxml.declarations.calldef.argument_t>} + @param inputexpr: The expression that is used as input parameter for the Python function call inside the virtual function + @type inputexpr: str """ if self._funcs_initialized: raise ValueError, "insert_arg() may only be called before function initialization." @@ -369,15 +381,67 @@ else: if idx<0: idx += len(self.wrapper_func.arg_list)+2 + + idx += self._insert_arg_idx_offset self.wrapper_func.arg_list.insert(idx-1, arg) # What to insert? - self.virtual_func.input_params.insert(idx-1, "???") + self.virtual_func.input_params.insert(idx-1, inputexpr) # Adjust the argument index map for i in range(idx-1,len(self.argidxmap)): if self.argidxmap[i]!=None: self.argidxmap[i] += 1 + # py_result_expr + def py_result_expr(self, local_wrapper_var): + """Return a C++ expression that references one particular item of the result tuple in the virtual function. + + This method is supposed to be used in the virtual_post_call() method + of function transformers when the result object of the Python call + is required. It relieves the transformer from having to check whether + its value is the only output value or not (in the former case the + value is an arbitrary Python object, in the latter case it is always + a tuple). + + For example, if a function transformer allocates a variable and + adds it to the result expressions of the wrapper function (so that + the wrapper function returns the value of this variable) then + the corresponding virtual function has to receive this value + and convert it to a C++ value. Suppose the result of invoking + the Python function inside the virtual function is stored in + the variable "pyresult" (which is of type "object"). The transformer + object that has to access its output value has to distinguish + two cases: + + - Its output value was the only output, then it references the + output value simply with "pyresult". + - There are also other output values, then it references its + output value with "pyresult[n]" where n is the position of + the output variable in the result tuple. + + To relieve the transformer from the burden of having to perform + this test, py_result_expr() can be used which generates the + appropriate expression. + + @param local_wrapper_var: The name of the local variable inside the wrapper that is part of the result tuple + @type local_wrapper_var: str + @return: The C++ expression that references the result item + @rtype: str + """ + # Get the name of the result variable + pyresult = self.virtual_func.result_var + # Determine the index of the requested local wrapper variable + try: + idx = self.wrapper_func.result_exprs.index(local_wrapper_var) + except ValueError: + raise ValueError, "The local variable '%s' is not returned by the wrapper function." + + # Return the C++ expression + if len(self.wrapper_func.result_exprs)==1: + return pyresult + else: + return "%s[%d]"%(pyresult, idx) + # require_include def require_include(self, include, where=None): """Declare an include file that is required for the code to compile. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-14 17:42:22
|
Revision: 546 http://svn.sourceforge.net/pygccxml/?rev=546&view=rev Author: mbaas Date: 2006-09-14 10:42:19 -0700 (Thu, 14 Sep 2006) Log Message: ----------- Two bug fixes: 1) The parameter list didn't use boost::ref() etc. 2) The internal return_virtual_result_t policy didn't properly access the result value which could lead to a Python exception. Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-14 13:06:59 UTC (rev 545) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-14 17:42:19 UTC (rev 546) @@ -11,6 +11,7 @@ from pygccxml import declarations from code_manager import code_manager_t, wrapper_code_manager_t from function_transformer import function_transformer_t +from pyplusplus import decl_wrappers # substitution_manager_t class substitution_manager_t: @@ -197,7 +198,7 @@ self.virtual_func.class_name = wrapper_class self.virtual_func.FUNC_NAME = decl.name self.virtual_func.CALL_FUNC_NAME = decl.name - self.virtual_func.input_params = map(lambda a: a.name, decl.arguments) + self.virtual_func.input_params = map(lambda a: self._function_call_arg(a), decl.arguments) self.wrapper_func.arg_list = decl.arguments[:] self.wrapper_func.class_name = wrapper_class @@ -542,7 +543,40 @@ decl = parent return None + # _function_call_arg + def _function_call_arg(self, arg): + """Return the C++ expression that represents arg in the actual function call. + This helper method returns a string that contains a C++ expression + that references the argument arg. This expression is supposed to + be used in the function invocation of which this is one input + parameter. The return value is one of three variants: + + - <name> + - boost::ref(<name>) + - boost::python::ptr(<name>) + + @rtype: str + """ + arg_type = declarations.remove_alias( arg.type ) + if decl_wrappers.python_traits.is_immutable( arg_type ): + return arg.name + elif declarations.is_reference( arg_type ): + no_ref = declarations.remove_reference( arg_type ) + if decl_wrappers.python_traits.is_immutable( no_ref ): + #pass by value + return arg.name + else: + #pass by ref + return 'boost::ref(%s)' % arg.name + elif declarations.is_pointer( arg_type ) \ + and not declarations.is_pointer( arg_type.base ) \ + and not decl_wrappers.python_traits.is_immutable( arg_type.base ): + return 'boost::python::ptr(%s)' % arg.name + else: + return arg.name + + # return_virtual_result_t class return_virtual_result_t(function_transformer_t): """Extract and return the result value of the virtual function. @@ -575,13 +609,19 @@ # value of the C++ function call. If the value exists it is extracted # from the Python result tuple, converted to C++ and returned from # the virtual function. If it does not exist, do nothing. +# try: +# resultidx = sm.wrapper_func.result_exprs.index(sm.wrapper_func.result_var) +# except ValueError: +# return + try: - resultidx = sm.wrapper_func.result_exprs.index(sm.wrapper_func.result_var) + resexpr = sm.py_result_expr(self.result_var) except ValueError: return res = "// Extract the C++ return value\n" - res += "%s = boost::python::extract<%s>(%s[%d]);"%(self.result_var, sm.virtual_func.ret_type, sm.virtual_func.result_var, resultidx) + res += "%s = boost::python::extract<%s>(%s);"%(self.result_var, sm.virtual_func.ret_type, resexpr) +# res += "%s = boost::python::extract<%s>(%s[%d]);"%(self.result_var, sm.virtual_func.ret_type, sm.virtual_func.result_var, resultidx) return res This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-26 09:06:49
|
Revision: 590 http://svn.sourceforge.net/pygccxml/?rev=590&view=rev Author: mbaas Date: 2006-09-26 02:06:43 -0700 (Tue, 26 Sep 2006) Log Message: ----------- Take static members into account when setting up the substitution variables. Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-26 08:54:57 UTC (rev 589) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-26 09:06:43 UTC (rev 590) @@ -230,11 +230,14 @@ # Check if we're dealing with a member function... clsdecl = self._class_decl(decl) if clsdecl!=None: - selfname = self.wrapper_func._make_name_unique("self") - selfarg = declarations.argument_t(selfname, declarations.dummy_type_t("%s&"%clsdecl.name)) - self.wrapper_func.arg_list.insert(0, selfarg) - self.wrapper_func.CALL_FUNC_NAME = "%s.%s"%(selfname, self.wrapper_func.CALL_FUNC_NAME) - self._insert_arg_idx_offset = 1 + if decl.has_static: + self.wrapper_func.CALL_FUNC_NAME = "%s::%s"%(clsdecl.name, self.wrapper_func.CALL_FUNC_NAME) + else: + selfname = self.wrapper_func._make_name_unique("self") + selfarg = declarations.argument_t(selfname, declarations.dummy_type_t("%s&"%clsdecl.name)) + self.wrapper_func.arg_list.insert(0, selfarg) + self.wrapper_func.CALL_FUNC_NAME = "%s.%s"%(selfname, self.wrapper_func.CALL_FUNC_NAME) + self._insert_arg_idx_offset = 1 # Argument index map # Original argument index ---> Input arg index (indices are 0-based!) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-29 16:36:57
|
Revision: 606 http://svn.sourceforge.net/pygccxml/?rev=606&view=rev Author: mbaas Date: 2006-09-29 09:36:53 -0700 (Fri, 29 Sep 2006) Log Message: ----------- A few minor fixes: Remove references on return types. Use the full name for object types. Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-29 15:57:42 UTC (rev 605) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-29 16:36:53 UTC (rev 606) @@ -214,8 +214,10 @@ ret_type = None else: ret_type = decl.return_type - self.wrapper_func.result_type = str(ret_type) +# self.wrapper_func.result_type = str(ret_type) + self.wrapper_func.result_type = str(declarations.type_traits.remove_reference(ret_type)) self.wrapper_func.result_var = self.wrapper_func.declare_local("result", self.wrapper_func.result_type) +# self.wrapper_func.result_var = self.wrapper_func.allocate_local("result") self.wrapper_func.result_exprs = [self.wrapper_func.result_var] self.virtual_func.ret_type = ret_type @@ -231,10 +233,10 @@ clsdecl = self._class_decl(decl) if clsdecl!=None: if decl.has_static: - self.wrapper_func.CALL_FUNC_NAME = "%s::%s"%(clsdecl.name, self.wrapper_func.CALL_FUNC_NAME) + self.wrapper_func.CALL_FUNC_NAME = "%s::%s"%(declarations.full_name(clsdecl), self.wrapper_func.CALL_FUNC_NAME) else: selfname = self.wrapper_func._make_name_unique("self") - selfarg = declarations.argument_t(selfname, declarations.dummy_type_t("%s&"%clsdecl.name)) + selfarg = declarations.argument_t(selfname, declarations.dummy_type_t("%s&"%declarations.full_name(clsdecl))) self.wrapper_func.arg_list.insert(0, selfarg) self.wrapper_func.CALL_FUNC_NAME = "%s.%s"%(selfname, self.wrapper_func.CALL_FUNC_NAME) self._insert_arg_idx_offset = 1 @@ -280,6 +282,7 @@ # inside the virtual function. if len(self.wrapper_func.result_exprs)>0: self.virtual_func.result_type = "boost::python::object" +# self.virtual_func.result_var = self.virtual_func.allocate_local("pyresult") self.virtual_func.result_var = self.virtual_func.declare_local("pyresult", self.virtual_func.result_type) # self.virtual_func.result_expr = self.virtual_func.result_var This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |