static void
arguments_from_ruby(GICallableInfo *info, VALUE rb_arguments,
                    GArray *in_args, GArray *out_args,
                    GPtrArray *args_metadata)
{
    gint i, n_args;

    allocate_arguments(info, in_args, out_args, args_metadata);
    fill_metadata(args_metadata);

    n_args = g_callable_info_get_n_args(info);
    for (i = 0; i < n_args; i++) {
        RBGIArgMetadata *metadata;

        metadata = g_ptr_array_index(args_metadata, i);
        if (metadata->in_arg_index != -1) {
            in_argument_from_ruby(metadata, rb_arguments, in_args);
        } else {
            out_argument_from_ruby(metadata, out_args);
        }
    }
}
Beispiel #2
0
static void
ffi_closure_callback(G_GNUC_UNUSED ffi_cif *cif,
                     void *result,
                     void **raw_args,
                     void *data)
{
    RBGICallback *callback = data;
    RBGICallbackData *callback_data = NULL;
    GArray *in_args;
    GArray *out_args;
    GPtrArray *args_metadata;
    VALUE rb_results;

    arguments_init(&in_args, &out_args, &args_metadata);
    allocate_arguments(callback->callback_info,
                       in_args,
                       out_args,
                       args_metadata);
    fill_metadata(args_metadata, callback->callback_info);
    arguments_from_raw_data(callback->callback_info,
                            raw_args,
                            in_args,
                            out_args,
                            args_metadata);

    {
        guint i;

        for (i = 0; i < args_metadata->len; i++) {
            RBGIArgMetadata *metadata;

            metadata = g_ptr_array_index(args_metadata, i);
            if (!metadata->closure_p) {
                continue;
            }

            callback_data = *((RBGICallbackData **)(raw_args[i]));
            break;
        }
    }

    {
        ID id_call;
        GArray *rb_args;

        rb_args = g_array_new(FALSE, FALSE, sizeof(VALUE));
        in_arguments_to_ruby(in_args,
                             out_args,
                             args_metadata,
                             rb_args);
        CONST_ID(id_call, "call");
        /* TODO: use rb_protect() */
        rb_results = rb_funcallv(callback_data->rb_callback,
                                 id_call,
                                 rb_args->len,
                                 (VALUE *)(rb_args->data));
        g_array_free(rb_args, TRUE);
    }

    out_arguments_to_raw_data(callback->callback_info,
                              rb_results,
                              result,
                              out_args,
                              args_metadata);

    if (callback_data->metadata->scope_type == GI_SCOPE_TYPE_ASYNC) {
        rb_gi_callback_data_free(callback_data);
    }
}