예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}