static PyObject * _invoke_marshal_out_args (PyGIInvokeState *state, PyGIFunctionCache *function_cache) { PyGICallableCache *cache = (PyGICallableCache *) function_cache; PyObject *py_out = NULL; PyObject *py_return = NULL; gssize n_out_args = cache->n_to_py_args - cache->n_to_py_child_args; if (cache->return_cache) { if (!cache->return_cache->is_skipped) { py_return = cache->return_cache->to_py_marshaller ( state, cache, cache->return_cache, &state->return_arg); if (py_return == NULL) { pygi_marshal_cleanup_args_return_fail (state, cache); return NULL; } } else { if (cache->return_cache->transfer == GI_TRANSFER_EVERYTHING) { PyGIMarshalCleanupFunc to_py_cleanup = cache->return_cache->to_py_cleanup; if (to_py_cleanup != NULL) to_py_cleanup ( state, cache->return_cache, NULL, &state->return_arg, FALSE); } } } if (n_out_args == 0) { if (cache->return_cache->is_skipped && state->error == NULL) { /* we skip the return value and have no (out) arguments to return, * so py_return should be NULL. But we must not return NULL, * otherwise Python will expect an exception. */ g_assert (py_return == NULL); Py_INCREF(Py_None); py_return = Py_None; } py_out = py_return; } else if (!cache->has_return && n_out_args == 1) { /* if we get here there is one out arg an no return */ PyGIArgCache *arg_cache = (PyGIArgCache *)cache->to_py_args->data; py_out = arg_cache->to_py_marshaller (state, cache, arg_cache, state->args[arg_cache->c_arg_index].arg_pointer.v_pointer); if (py_out == NULL) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, 0); return NULL; } } else { /* return a tuple */ gssize py_arg_index = 0; GSList *cache_item = cache->to_py_args; gssize tuple_len = cache->has_return + n_out_args; py_out = pygi_resulttuple_new (cache->resulttuple_type, tuple_len); if (py_out == NULL) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, py_arg_index); return NULL; } if (cache->has_return) { PyTuple_SET_ITEM (py_out, py_arg_index, py_return); py_arg_index++; } for (; py_arg_index < tuple_len; py_arg_index++) { PyGIArgCache *arg_cache = (PyGIArgCache *)cache_item->data; PyObject *py_obj = arg_cache->to_py_marshaller (state, cache, arg_cache, state->args[arg_cache->c_arg_index].arg_pointer.v_pointer); if (py_obj == NULL) { if (cache->has_return) py_arg_index--; pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, py_arg_index); Py_DECREF (py_out); return NULL; } PyTuple_SET_ITEM (py_out, py_arg_index, py_obj); cache_item = cache_item->next; } } return py_out; }
static gboolean _pygi_closure_set_out_arguments (PyGIInvokeState *state, PyGICallableCache *cache, PyObject *py_retval, void *resp) { gssize i; gssize i_py_retval = 0; gboolean success; if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) { PyObject *item = py_retval; if (PyTuple_Check (py_retval)) { item = PyTuple_GET_ITEM (py_retval, 0); } success = cache->return_cache->from_py_marshaller (state, cache, cache->return_cache, item, &state->return_arg, &state->args[0].arg_cleanup_data); if (!success) { pygi_marshal_cleanup_args_return_fail (state, cache); return FALSE; } _pygi_closure_assign_pyobj_to_retval (resp, &state->return_arg, cache->return_cache); i_py_retval++; } for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i); if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) { PyObject *item = py_retval; if (arg_cache->type_tag == GI_TYPE_TAG_ERROR) { * (GError **) state->args[i].arg_pointer.v_pointer = NULL; continue; } if (PyTuple_Check (py_retval)) { item = PyTuple_GET_ITEM (py_retval, i_py_retval); } else if (i_py_retval != 0) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, i_py_retval); return FALSE; } success = arg_cache->from_py_marshaller (state, cache, arg_cache, item, &state->args[i].arg_value, &state->args[i_py_retval].arg_cleanup_data); if (!success) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, i_py_retval); return FALSE; } _pygi_closure_assign_pyobj_to_out_argument (state->args[i].arg_pointer.v_pointer, &state->args[i].arg_value, arg_cache); i_py_retval++; } } return TRUE; }