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); } } }
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); } }