static void
in_callback_argument_from_ruby(RBGIArgMetadata *metadata, GArray *in_args)
{
    gpointer callback;
    GIArgInfo *arg_info;
    GIArgument *callback_argument;

    arg_info = &(metadata->arg_info);
    callback = find_callback_function(arg_info);
    if (!callback) {
        GITypeInfo type_info;
        GIBaseInfo *interface_info;
        VALUE rb_type_name;
        g_arg_info_load_type(arg_info, &type_info);
        interface_info = g_type_info_get_interface(&type_info);
        rb_type_name = CSTR2RVAL(g_base_info_get_name(interface_info));
        g_base_info_unref(interface_info);
        rb_raise(rb_eNotImpError,
                 "TODO: <%s>(%s) callback is not supported yet.",
                 RVAL2CSTR(rb_type_name),
                 g_base_info_get_name(arg_info));
    }

    callback_argument = &(g_array_index(in_args,
                                        GIArgument,
                                        metadata->in_arg_index));
    callback_argument->v_pointer = callback;

    if (metadata->closure_in_arg_index != -1) {
        RBGICallbackData *callback_data;
        GIArgument *closure_argument;

        callback_data = ALLOC(RBGICallbackData);
        callback_data->metadata = metadata;
        callback_data->rb_callback = rb_block_proc();
        callback_data_guard_from_gc(callback_data);
        closure_argument = &(g_array_index(in_args,
                                           GIArgument,
                                           metadata->closure_in_arg_index));
        closure_argument->v_pointer = callback_data;
    }

    if (metadata->destroy_in_arg_index != -1) {
        GIArgument *destroy_argument;
        destroy_argument = &(g_array_index(in_args,
                                           GIArgument,
                                           metadata->destroy_in_arg_index));
        destroy_argument->v_pointer = destroy_notify;
    }
}
static void
in_callback_argument_from_ruby(RBGIArgMetadata *metadata, GArray *in_args)
{
    gpointer callback_function;
    GIArgInfo *arg_info;
    GIArgument *callback_argument;
    GIArgument *closure_argument = NULL;
    GIArgument *destroy_argument = NULL;
    RBGICallback *callback = NULL;

    arg_info = &(metadata->arg_info);

    callback_argument = &(g_array_index(in_args,
                                        GIArgument,
                                        metadata->in_arg_index));
    if (metadata->closure_in_arg_index != -1) {
        closure_argument = &(g_array_index(in_args,
                                           GIArgument,
                                           metadata->closure_in_arg_index));
    }
    if (metadata->destroy_in_arg_index != -1) {
        destroy_argument = &(g_array_index(in_args,
                                           GIArgument,
                                           metadata->destroy_in_arg_index));
    }

    if (!rb_block_given_p() && g_arg_info_may_be_null(arg_info)) {
        callback_argument->v_pointer = NULL;
        if (closure_argument) {
            closure_argument->v_pointer = NULL;
        }
        if (destroy_argument) {
            destroy_argument->v_pointer = NULL;
        }
        return;
    }

    callback_function = find_callback_function(arg_info);
    if (callback_function) {
        callback_argument->v_pointer = callback_function;
    } else {
        callback = RB_ZALLOC(RBGICallback);
        callback->type_info = g_arg_info_get_type(arg_info);
        callback->callback_info = g_type_info_get_interface(callback->type_info);
        callback->closure =
            g_callable_info_prepare_closure(callback->callback_info,
                                            &(callback->cif),
                                            ffi_closure_callback,
                                            callback);
        callback_argument->v_pointer = callback->closure;
    }

    if (closure_argument) {
        RBGICallbackData *callback_data;

        callback_data = ALLOC(RBGICallbackData);
        callback_data->callback = callback;
        callback_data->metadata = metadata;
        callback_data->rb_callback = rb_block_proc();
        callback_data_guard_from_gc(callback_data);
        closure_argument->v_pointer = callback_data;
    }

    if (destroy_argument) {
        destroy_argument->v_pointer = destroy_notify;
    }
}