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; }
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_convert_arguments (PyGIInvokeState *state, PyGIClosureCache *closure_cache) { PyGICallableCache *cache = (PyGICallableCache *) closure_cache; gssize n_in_args = 0; gssize i; for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache; arg_cache = g_ptr_array_index (cache->args_cache, i); if (arg_cache->direction & PYGI_DIRECTION_TO_PYTHON) { PyObject *value; if (cache->user_data_index == i) { if (state->user_data == NULL) { /* user_data can be NULL for connect functions which don't accept * user_data or as the default for user_data in the middle of function * arguments. */ Py_INCREF (Py_None); value = Py_None; } else { /* Extend the callbacks args with user_data as variable args. */ gssize j, user_data_len; PyObject *py_user_data = state->user_data; if (!PyTuple_Check (py_user_data)) { PyErr_SetString (PyExc_TypeError, "expected tuple for callback user_data"); return FALSE; } user_data_len = PyTuple_Size (py_user_data); _PyTuple_Resize (&state->py_in_args, state->n_py_in_args + user_data_len - 1); for (j = 0; j < user_data_len; j++, n_in_args++) { value = PyTuple_GetItem (py_user_data, j); Py_INCREF (value); PyTuple_SET_ITEM (state->py_in_args, n_in_args, value); } /* We can assume user_data args are never going to be inout, * so just continue here. */ continue; } } else if (arg_cache->meta_type != PYGI_META_ARG_TYPE_PARENT) { continue; } else { value = arg_cache->to_py_marshaller (state, cache, arg_cache, &state->args[i].arg_value); if (value == NULL) { pygi_marshal_cleanup_args_to_py_parameter_fail (state, cache, i); return FALSE; } } PyTuple_SET_ITEM (state->py_in_args, n_in_args, value); n_in_args++; } } if (_PyTuple_Resize (&state->py_in_args, n_in_args) == -1) return FALSE; return TRUE; }