support for multiple return values from rna functions & support for returning arrays, (no functions are using this yet).

patch from Elia Sarti, (vekoon) with some modifications mainly for the python api.

- multiple values are returned as a typle in the order that are defined.
- added support for registered types returning multiple arguments (untested).
- renamed func->ret --> func->c_ret, since this only defines what the C function returns.
This commit is contained in:
2010-01-02 10:42:38 +00:00
parent 382e52e5c7
commit e83940d994
7 changed files with 129 additions and 47 deletions

View File

@@ -2564,11 +2564,13 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
PointerRNA funcptr;
ParameterList parms;
ParameterIterator iter;
PropertyRNA *pret, *parm;
PropertyRNA *parm;
PyObject *ret, *item;
int i, args_len, parms_len, flag, err= 0, kw_tot= 0, kw_arg;
int i, args_len, parms_len, ret_len, flag, err= 0, kw_tot= 0, kw_arg;
const char *parm_id;
void *retdata= NULL;
PropertyRNA *pret_single= NULL;
void *retdata_single= NULL;
/* Should never happen but it does in rare cases */
if(self_ptr==NULL) {
@@ -2586,12 +2588,12 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
* the same ID as the functions. */
RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr);
pret= RNA_function_return(self_func);
args_len= PyTuple_GET_SIZE(args);
RNA_parameter_list_create(&parms, self_ptr, self_func);
RNA_parameter_list_begin(&parms, &iter);
parms_len = RNA_parameter_list_size(&parms);
parms_len= RNA_parameter_list_size(&parms);
ret_len= 0;
if(args_len + (kw ? PyDict_Size(kw):0) > parms_len) {
PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): takes at most %d arguments, got %d", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parms_len, args_len);
@@ -2601,14 +2603,20 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
/* parse function parameters */
for (i= 0; iter.valid && err==0; RNA_parameter_list_next(&iter)) {
parm= iter.parm;
flag= RNA_property_flag(parm);
/* only useful for single argument returns, we'll need another list loop for multiple */
if (flag & PROP_RETURN) {
ret_len++;
if (pret_single==NULL) {
pret_single= parm;
retdata_single= iter.data;
}
if (parm==pret) {
retdata= iter.data;
continue;
}
parm_id= RNA_property_identifier(parm);
flag= RNA_property_flag(parm);
item= NULL;
if ((i < args_len) && (flag & PROP_REQUIRED)) {
@@ -2740,8 +2748,25 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
/* return value */
if(err==0) {
if(pret) {
ret= pyrna_param_to_py(&funcptr, pret, retdata);
if (ret_len > 0) {
if (ret_len > 1) {
ret= PyTuple_New(ret_len);
i= 0; /* arg index */
RNA_parameter_list_begin(&parms, &iter);
for(; iter.valid; RNA_parameter_list_next(&iter)) {
parm= iter.parm;
flag= RNA_property_flag(parm);
if (flag & PROP_RETURN)
PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data));
}
RNA_parameter_list_end(&iter);
}
else
ret= pyrna_param_to_py(&funcptr, pret_single, retdata_single);
/* possible there is an error in conversion */
if(ret==NULL)
@@ -3980,15 +4005,18 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
extern void BPY_update_modules( void ); //XXX temp solution
/* TODO - multiple return values like with rna functions */
static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
{
PyObject *args;
PyObject *ret= NULL, *py_class, *py_class_instance, *item, *parmitem;
PropertyRNA *pret= NULL, *parm;
PropertyRNA *parm;
ParameterIterator iter;
PointerRNA funcptr;
void *retdata= NULL;
int err= 0, i, flag;
int err= 0, i, flag, ret_len=0;
PropertyRNA *pret_single= NULL;
void *retdata_single= NULL;
PyGILState_STATE gilstate;
@@ -4014,10 +4042,9 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
if (py_class_instance) { /* Initializing the class worked, now run its invoke function */
item= PyObject_GetAttrString(py_class, RNA_function_identifier(func));
flag= RNA_function_flag(func);
// flag= RNA_function_flag(func);
if(item) {
pret= RNA_function_return(func);
RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
@@ -4028,9 +4055,16 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
/* parse function parameters */
for (i= 1; iter.valid; RNA_parameter_list_next(&iter)) {
parm= iter.parm;
flag= RNA_property_flag(parm);
/* only useful for single argument returns, we'll need another list loop for multiple */
if (flag & PROP_RETURN) {
ret_len++;
if (pret_single==NULL) {
pret_single= parm;
retdata_single= iter.data;
}
if (parm==pret) {
retdata= iter.data;
continue;
}
@@ -4060,8 +4094,37 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
err= -1;
}
else {
if(retdata)
err= pyrna_py_to_prop(&funcptr, pret, retdata, ret, "calling class function:");
if(ret_len==1) {
err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "calling class function:");
}
else if (ret_len > 1) {
if(PyTuple_Check(ret)==0) {
PyErr_Format(PyExc_RuntimeError, "expected class %.200s, function %.200s to return a tuple of size %d.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), ret_len);
err= -1;
}
else if (PyTuple_GET_SIZE(ret) != ret_len) {
PyErr_Format(PyExc_RuntimeError, "class %.200s, function %.200s to returned %d items, expected %d.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), PyTuple_GET_SIZE(ret), ret_len);
err= -1;
}
else {
RNA_parameter_list_begin(parms, &iter);
/* parse function parameters */
for (i= 0; iter.valid; RNA_parameter_list_next(&iter)) {
parm= iter.parm;
flag= RNA_property_flag(parm);
/* only useful for single argument returns, we'll need another list loop for multiple */
if (flag & PROP_RETURN) {
err= pyrna_py_to_prop(&funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:");
if(err)
break;
}
}
}
}
Py_DECREF(ret);
}