Example #1
0
VALUE
rb_gi_function_info_invoke_raw(GIFunctionInfo *info,
                               VALUE rb_info,
                               VALUE rb_receiver,
                               VALUE rb_arguments,
                               GIArgument *return_value,
                               VALUE *rb_return_value)
{
    GICallableInfo *callable_info;
    GIArgument receiver;
    GArray *in_args, *out_args;
    GPtrArray *args_metadata;
    VALUE rb_out_args = Qnil;
    gboolean succeeded;
    GError *error = NULL;
    gboolean unlock_gvl = FALSE;
    gboolean rb_receiver_is_class = FALSE;

    unlock_gvl = RVAL2CBOOL(rb_funcall(rb_info, rb_intern("unlock_gvl?"), 0));
    if (NIL_P(rb_receiver)) {
        receiver.v_pointer = NULL;
    } else {
        if (gobject_based_p((GIBaseInfo *)info)) {
            receiver.v_pointer = RVAL2GOBJ(rb_receiver);
        } else if (RVAL2CBOOL(rb_obj_is_kind_of(rb_receiver, rb_cClass)) &&
                   rb_respond_to(rb_receiver, rb_intern("gtype"))) {
            GObjectClass *object_class;
            rb_receiver_is_class = TRUE;
            object_class = g_type_class_ref(CLASS2GTYPE(rb_receiver));
            receiver.v_pointer = object_class;
        } else {
            receiver.v_pointer = DATA_PTR(rb_receiver);
        }
    }
    rb_arguments = rbg_to_array(rb_arguments);

    callable_info = (GICallableInfo *)info;
    arguments_init(&in_args, &out_args, &args_metadata);
    if (receiver.v_pointer) {
        g_array_append_val(in_args, receiver);
    }
    arguments_from_ruby(callable_info, rb_receiver, rb_arguments,
                        in_args, out_args, args_metadata);
    {
        InvokeData data;
        data.info = info;
        data.in_args = in_args;
        data.out_args = out_args;
        data.error = &error;
        if (unlock_gvl) {
            rb_thread_call_without_gvl(
                rb_gi_function_info_invoke_raw_call_without_gvl_body, &data,
                NULL, NULL);
        } else {
            rb_gi_function_info_invoke_raw_call(&data);
        }
        succeeded = data.succeeded;

        if (rb_receiver_is_class) {
            g_type_class_unref(receiver.v_pointer);
        }

        if (return_value) {
            *return_value = data.return_value;
        }
        if (rb_return_value) {
            if (succeeded) {
                *rb_return_value = GI_RETURN_ARGUMENT2RVAL(callable_info,
                                                           &(data.return_value),
                                                           in_args,
                                                           out_args,
                                                           args_metadata);
            } else {
                *rb_return_value = Qnil;
            }
        }
    }

    if (succeeded) {
        rb_out_args = out_arguments_to_ruby(callable_info,
                                            in_args, out_args,
                                            args_metadata);
    }
    arguments_free(rb_arguments, in_args, out_args, args_metadata);
    if (!succeeded) {
        RG_RAISE_ERROR(error);
    }

    if (!NIL_P(rb_out_args) && RARRAY_LEN(rb_out_args) == 1) {
        VALUE rb_out_arg;
        rb_out_arg = RARRAY_PTR(rb_out_args)[0];
        if (rb_obj_is_kind_of(rb_out_arg, rb_eException)) {
            rb_exc_raise(rb_out_arg);
        }
    }

    return rb_out_args;
}
VALUE
rb_gi_function_info_invoke_raw(GIFunctionInfo *info, VALUE rb_options,
                               GIArgument *return_value)
{
    GICallableInfo *callable_info;
    GIArgument receiver;
    GArray *in_args, *out_args;
    GPtrArray *args_metadata;
    VALUE rb_out_args = Qnil;
    gboolean succeeded;
    GError *error = NULL;
    gboolean unlock_gvl = FALSE;
    VALUE rb_receiver, rb_arguments, rb_unlock_gvl;

    if (RB_TYPE_P(rb_options, RUBY_T_ARRAY)) {
        rb_receiver = Qnil;
        rb_arguments = rb_options;
        rb_unlock_gvl = Qnil;
    } else if (NIL_P(rb_options)) {
        rb_receiver = Qnil;
        rb_arguments = rb_ary_new();
        rb_unlock_gvl = Qnil;
    } else {
        rb_options = rbg_check_hash_type(rb_options);
        rbg_scan_options(rb_options,
                         "receiver", &rb_receiver,
                         "arguments", &rb_arguments,
                         "unlock_gvl", &rb_unlock_gvl,
                         NULL);
    }

    if (NIL_P(rb_receiver)) {
        receiver.v_pointer = NULL;
    } else {
        if (gobject_based_p((GIBaseInfo *)info)) {
            receiver.v_pointer = RVAL2GOBJ(rb_receiver);
        } else {
            receiver.v_pointer = DATA_PTR(rb_receiver);
        }
    }
    rb_arguments = rbg_to_array(rb_arguments);
    if (!NIL_P(rb_unlock_gvl) && RVAL2CBOOL(rb_unlock_gvl)) {
        unlock_gvl = TRUE;
    }

    callable_info = (GICallableInfo *)info;
    arguments_init(&in_args, &out_args, &args_metadata);
    if (receiver.v_pointer) {
        g_array_append_val(in_args, receiver);
    }
    arguments_from_ruby(callable_info, rb_arguments,
                        in_args, out_args, args_metadata);
    {
        InvokeData data;
        data.info = info;
        data.in_args = in_args;
        data.out_args = out_args;
        data.return_value = return_value;
        data.error = &error;
        if (unlock_gvl) {
            rb_thread_call_without_gvl(
                rb_gi_function_info_invoke_raw_call_without_gvl_body, &data,
                NULL, NULL);
        } else {
            rb_gi_function_info_invoke_raw_call(&data);
        }
        succeeded = data.succeeded;
    }

    if (succeeded) {
        rb_out_args = out_arguments_to_ruby(callable_info,
                                            in_args, out_args,
                                            args_metadata);
    }
    arguments_free(in_args, out_args, args_metadata);
    if (!succeeded) {
        RG_RAISE_ERROR(error);
    }

    if (!NIL_P(rb_out_args) && RARRAY_LEN(rb_out_args) == 1) {
        VALUE rb_out_arg;
        rb_out_arg = RARRAY_PTR(rb_out_args)[0];
        if (rb_obj_is_kind_of(rb_out_arg, rb_eException)) {
            rb_exc_raise(rb_out_arg);
        }
    }

    return rb_out_args;
}