static void peas_gi_split_in_and_out_arguments (GICallableInfo *callable_info, GIArgument *args, GIArgument *in_args, guint *n_in_args, GIArgument *out_args, guint *n_out_args) { gint n_args, i; GIArgInfo arg_info; g_return_if_fail (callable_info != NULL); n_args = g_callable_info_get_n_args (callable_info); for (i = 0; i < n_args; i++) { g_callable_info_load_arg (callable_info, i, &arg_info); switch (g_arg_info_get_direction (&arg_info)) { case GI_DIRECTION_IN: in_args[(*n_in_args)++] = args[i]; break; case GI_DIRECTION_INOUT: in_args[(*n_in_args)++] = args[i]; out_args[(*n_out_args)++] = args[i]; break; case GI_DIRECTION_OUT: out_args[(*n_out_args)++] = args[i]; break; } } }
/** * _pygi_argument_array_length_marshal: * @length_arg_index: Index of length argument in the callables args list. * @user_data1: (type Array(GValue)): Array of GValue arguments to retrieve length * @user_data2: (type GICallableInfo): Callable info to get the argument from. * * Generic marshalling policy for array length arguments in callables. * * Returns: The length of the array or -1 on failure. */ gssize _pygi_argument_array_length_marshal (gsize length_arg_index, void *user_data1, void *user_data2) { GIArgInfo length_arg_info; GITypeInfo length_type_info; GIArgument length_arg; gssize array_len = -1; GValue *values = (GValue *)user_data1; GICallableInfo *callable_info = (GICallableInfo *)user_data2; g_callable_info_load_arg (callable_info, length_arg_index, &length_arg_info); g_arg_info_load_type (&length_arg_info, &length_type_info); length_arg = _pygi_argument_from_g_value (&(values[length_arg_index]), &length_type_info); if (!pygi_argument_to_gssize (&length_arg, g_type_info_get_tag (&length_type_info), &array_len)) { return -1; } return array_len; }
static void allocate_arguments(GICallableInfo *info, GArray *in_args, GArray *out_args, GPtrArray *args_metadata) { gint i, n_args; gint rb_arg_index = 0; n_args = g_callable_info_get_n_args(info); for (i = 0; i < n_args; i++) { GIArgument argument; RBGIArgMetadata *metadata; GIArgInfo *arg_info; GIDirection direction; memset(&argument, 0, sizeof(GIArgument)); metadata = ALLOC(RBGIArgMetadata); arg_info = &(metadata->arg_info); g_callable_info_load_arg(info, i, arg_info); metadata->scope_type = g_arg_info_get_scope(arg_info); metadata->direction = g_arg_info_get_direction(arg_info); metadata->callback_p = (metadata->scope_type != GI_SCOPE_TYPE_INVALID); metadata->closure_p = FALSE; metadata->destroy_p = FALSE; metadata->array_p = FALSE; metadata->array_length_p = FALSE; metadata->in_arg_index = -1; metadata->closure_in_arg_index = -1; metadata->destroy_in_arg_index = -1; metadata->array_in_arg_index = -1; metadata->array_length_in_arg_index = -1; metadata->array_length_arg_index = -1; metadata->rb_arg_index = -1; metadata->out_arg_index = -1; direction = metadata->direction; if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { metadata->in_arg_index = in_args->len; g_array_append_val(in_args, argument); metadata->rb_arg_index = rb_arg_index++; } if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { metadata->out_arg_index = out_args->len; g_array_append_val(out_args, argument); } g_ptr_array_add(args_metadata, metadata); } }
/* Gets or sets the length of the array. */ static void array_get_or_set_length (GITypeInfo *ti, gssize *get_length, gssize set_length, GICallableInfo *ci, void **args) { gint param = g_type_info_get_array_length (ti); if (param >= 0 && ci != NULL && param < g_callable_info_get_n_args (ci)) { GIArgInfo ai; GITypeInfo eti; GIArgument *val; g_callable_info_load_arg (ci, param, &ai); g_arg_info_load_type (&ai, &eti); if (g_arg_info_get_direction (&ai) == GI_DIRECTION_IN) /* For input parameters, value is directly pointed do by args table element. */ val = (GIArgument *) args[param]; else /* For output arguments, args table element points to pointer to value. */ val = *(GIArgument **) args[param]; switch (g_type_info_get_tag (&eti)) { #define HANDLE_ELT(tag, field) \ case GI_TYPE_TAG_ ## tag: \ if (get_length != NULL) \ *get_length = val->v_ ## field; \ else \ val->v_ ## field = set_length; \ break HANDLE_ELT(INT8, int8); HANDLE_ELT(UINT8, uint8); HANDLE_ELT(INT16, int16); HANDLE_ELT(UINT16, uint16); HANDLE_ELT(INT32, int32); HANDLE_ELT(UINT32, uint32); HANDLE_ELT(INT64, int64); HANDLE_ELT(UINT64, uint64); #undef HANDLE_ELT default: g_assert_not_reached (); } } }
static void handle_method_impl (ffi_cif *cif, gpointer result, gpointer *args, gpointer data) { MethodImpl *impl = (MethodImpl *) data; GIArgInfo arg_info; GITypeInfo type_info; GITypeInfo return_type_info; gint n_args, i; PeasExtensionWrapper *instance; GIArgument *arguments; GIArgument return_value; gboolean success; instance = *((PeasExtensionWrapper **) args[0]); g_assert (PEAS_IS_EXTENSION_WRAPPER (instance)); n_args = g_callable_info_get_n_args (impl->invoker_info); g_return_if_fail (n_args >= 0); arguments = g_newa (GIArgument, n_args); for (i = 0; i < n_args; i++) { g_callable_info_load_arg (impl->invoker_info, i, &arg_info); g_arg_info_load_type (&arg_info, &type_info); if (g_arg_info_get_direction (&arg_info) == GI_DIRECTION_IN) peas_gi_pointer_to_argument (&type_info, args[i + 1], &arguments[i]); else arguments[i].v_pointer = *((gpointer **) args[i + 1]); } success = peas_extension_wrapper_callv (instance, impl->interface_type, impl->invoker_info, impl->method_name, arguments, &return_value); if (!success) memset (&return_value, 0, sizeof (GIArgument)); g_callable_info_load_return_type (impl->invoker_info, &return_type_info); if (g_type_info_get_tag (&return_type_info) != GI_TYPE_TAG_VOID) peas_gi_argument_to_pointer (&return_type_info, &return_value, result); }
static gboolean source_func_p(GIArgInfo *info) { GITypeInfo type_info; GIBaseInfo *interface_info; GICallableInfo *callback_info; GITypeInfo return_type_info; GIArgInfo first_arg_info; GITypeInfo first_arg_type_info; g_arg_info_load_type(info, &type_info); if (g_type_info_get_tag(&type_info) != GI_TYPE_TAG_INTERFACE) { return FALSE; } interface_info = g_type_info_get_interface(&type_info); if (g_base_info_get_type(interface_info) != GI_INFO_TYPE_CALLBACK) { g_base_info_unref(interface_info); return FALSE; } callback_info = (GICallableInfo *)interface_info; g_callable_info_load_return_type(callback_info, &return_type_info); if (g_type_info_get_tag(&return_type_info) != GI_TYPE_TAG_BOOLEAN) { g_base_info_unref(interface_info); return FALSE; } if (g_callable_info_get_n_args(interface_info) != 1) { g_base_info_unref(interface_info); return FALSE; } g_callable_info_load_arg(interface_info, 0, &first_arg_info); g_arg_info_load_type(&first_arg_info, &first_arg_type_info); if (g_type_info_get_tag(&first_arg_type_info) != GI_TYPE_TAG_VOID) { g_base_info_unref(interface_info); return FALSE; } g_base_info_unref(interface_info); return TRUE; }
static gboolean peas_extension_gjs_call (PeasExtensionWrapper *exten, GType exten_type, GICallableInfo *func_info, const gchar *method_name, GIArgument *args, GIArgument *retval) { PeasExtensionGjs *gexten = PEAS_EXTENSION_GJS (exten); gboolean success = FALSE; jsval js_method, js_retval; jsval *js_args; CachedArg *arg_cache; gint i, n_args, nth_out_arg; gint n_in_args = 0; gint n_out_args = 0; gint cached_args = 0; /* Fetch the JS method we want to call */ if (!JS_GetProperty (gexten->js_context, gexten->js_object, method_name, &js_method) || JSVAL_IS_VOID (js_method)) { g_warning ("Method '%s.%s' was not found", g_type_name (exten_type), method_name); return FALSE; } if (JSVAL_IS_NULL (js_method) || !JSVAL_IS_OBJECT (js_method) || !JS_ObjectIsFunction (gexten->js_context, JSVAL_TO_OBJECT (js_method))) { g_warning ("Method '%s.%s' in not a function", g_type_name (exten_type), method_name); return FALSE; } n_args = g_callable_info_get_n_args (func_info); if (n_args < 0) { g_warn_if_fail (n_args >= 0); return FALSE; } js_args = g_newa (jsval, n_args); arg_cache = g_newa (CachedArg, n_args + 1); /* Return value is an out arg */ g_callable_info_load_return_type (func_info, &arg_cache[0].type_info); if (g_type_info_get_tag (&arg_cache[0].type_info) != GI_TYPE_TAG_VOID) { ++n_out_args; arg_cache[cached_args++].ptr = &retval->v_pointer; } /* Handle the arguments */ for (i = 0; i < n_args; ++i, ++cached_args) { GIDirection direction; g_callable_info_load_arg (func_info, i, &arg_cache[cached_args].arg_info); direction = g_arg_info_get_direction (&arg_cache[cached_args].arg_info); g_arg_info_load_type (&arg_cache[cached_args].arg_info, &arg_cache[cached_args].type_info); if (direction == GI_DIRECTION_IN && !gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++], &arg_cache[cached_args].type_info, &args[i], TRUE)) { g_warning ("Error failed to convert argument '%s'", g_base_info_get_name (&arg_cache[cached_args].arg_info)); return FALSE; } if (direction == GI_DIRECTION_INOUT) { GIArgument arg; peas_gi_pointer_to_argument (&arg_cache[cached_args].type_info, args[i].v_pointer, &arg); if (!gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++], &arg_cache[cached_args].type_info, &arg, TRUE)) { g_warning ("Error failed to convert argument '%s'", g_base_info_get_name (&arg_cache[cached_args].arg_info)); return FALSE; } } if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { ++n_out_args; arg_cache[cached_args].ptr = args[i].v_pointer; } } success = JS_CallFunctionValue (gexten->js_context, gexten->js_object, js_method, n_in_args, js_args, &js_retval); if (!success) { if (!gjs_log_exception (gexten->js_context, NULL)) { g_warning ("Error while calling '%s.%s'", g_type_name (exten_type), method_name); } return FALSE; } /* First we need to release in argument */ for (i = 0; i < cached_args; ++i) { GIDirection direction; /* First cached argument may be the return value */ if (i == 0 && cached_args > n_args) continue; direction = g_arg_info_get_direction (&arg_cache[i].arg_info); if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { GITransfer transfer; transfer = g_arg_info_get_ownership_transfer (&arg_cache[i].arg_info); if (!gjs_g_argument_release_in_arg (gexten->js_context, transfer, &arg_cache[i].type_info, &args[i])) { g_warning ("Error failed to release IN argument '%s'", g_base_info_get_name (&arg_cache[i].arg_info)); } } } /* Check that we have a valid return value */ if (n_out_args > 1) { if (!JSVAL_IS_OBJECT (js_retval) || !JS_IsArrayObject (gexten->js_context, JSVAL_TO_OBJECT (js_retval))) { g_warning ("Error return value is not an array"); return FALSE; } } /* Set out arguments */ for (i = 0, nth_out_arg = 0; i < cached_args && success; ++i) { gboolean is_return_value; is_return_value = i == 0 && cached_args > n_args; /* Return value does not have a GIArgInfo and is always out */ if (!is_return_value) { GIDirection direction; direction = g_arg_info_get_direction (&arg_cache[i].arg_info); if (direction == GI_DIRECTION_IN) continue; } if (n_out_args == 1) { success = set_out_arg (gexten->js_context, func_info, is_return_value, &arg_cache[i].arg_info, &arg_cache[i].type_info, arg_cache[i].ptr, js_retval); break; } else if (n_out_args > 1) { jsval js_value; if (!JS_GetElement (gexten->js_context, JSVAL_TO_OBJECT (js_retval), nth_out_arg++, &js_value) || js_value == JSVAL_VOID) { g_warning ("Error failed to get out argument %i", nth_out_arg); return FALSE; } else { success = set_out_arg (gexten->js_context, func_info, is_return_value, &arg_cache[i].arg_info, &arg_cache[i].type_info, arg_cache[i].ptr, js_value); } } } return success; }
static void pygi_signal_closure_marshal(GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { PyGILState_STATE state; PyGClosure *pc = (PyGClosure *)closure; PyObject *params, *ret = NULL; guint i; GISignalInfo *signal_info; gint n_sig_info_args; gint sig_info_highest_arg; GSList *list_item = NULL; GSList *pass_by_ref_structs = NULL; state = PyGILState_Ensure(); signal_info = ((PyGISignalClosure *)closure)->signal_info; n_sig_info_args = g_callable_info_get_n_args(signal_info); /* the first argument to a signal callback is instance, but instance is not counted in the introspection data */ sig_info_highest_arg = n_sig_info_args + 1; g_assert_cmpint(sig_info_highest_arg, ==, n_param_values); /* construct Python tuple for the parameter values */ params = PyTuple_New(n_param_values); for (i = 0; i < n_param_values; i++) { /* swap in a different initial data for connect_object() */ if (i == 0 && G_CCLOSURE_SWAP_DATA(closure)) { g_return_if_fail(pc->swap_data != NULL); Py_INCREF(pc->swap_data); PyTuple_SetItem(params, 0, pc->swap_data); } else if (i == 0) { PyObject *item = pyg_value_as_pyobject(¶m_values[i], FALSE); if (!item) { goto out; } PyTuple_SetItem(params, i, item); } else if (i < sig_info_highest_arg) { GIArgInfo arg_info; GITypeInfo type_info; GITypeTag type_tag; GIArgument arg = { 0, }; PyObject *item = NULL; gboolean free_array = FALSE; gboolean pass_struct_by_ref = FALSE; g_callable_info_load_arg(signal_info, i - 1, &arg_info); g_arg_info_load_type(&arg_info, &type_info); arg = _pygi_argument_from_g_value(¶m_values[i], &type_info); type_tag = g_type_info_get_tag (&type_info); if (type_tag == GI_TYPE_TAG_ARRAY) { /* Skip the self argument of param_values */ arg.v_pointer = _pygi_argument_to_array (&arg, _pygi_argument_array_length_marshal, (void *)(param_values + 1), signal_info, &type_info, &free_array); } /* Hack to ensure struct arguments are passed-by-reference allowing * callback implementors to modify the struct values. This is needed * for keeping backwards compatibility and should be removed in future * versions which support signal output arguments as return values. * See: https://bugzilla.gnome.org/show_bug.cgi?id=735486 * * Note the logic here must match the logic path taken in _pygi_argument_to_object. */ if (type_tag == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *info = g_type_info_get_interface (&type_info); GIInfoType info_type = g_base_info_get_type (info); if (info_type == GI_INFO_TYPE_STRUCT || info_type == GI_INFO_TYPE_BOXED || info_type == GI_INFO_TYPE_UNION) { GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info); gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) && (g_struct_info_is_foreign ((GIStructInfo *) info)); if (!is_foreign && !g_type_is_a (gtype, G_TYPE_VALUE) && g_type_is_a (gtype, G_TYPE_BOXED)) { pass_struct_by_ref = TRUE; } } g_base_info_unref (info); } if (pass_struct_by_ref) { /* transfer everything will ensure the struct is not copied when wrapped. */ item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_EVERYTHING); if (item && PyObject_IsInstance (item, (PyObject *) &PyGIBoxed_Type)) { ((PyGBoxed *)item)->free_on_dealloc = FALSE; pass_by_ref_structs = g_slist_prepend (pass_by_ref_structs, item); } } else { item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_NOTHING); } if (free_array) { g_array_free (arg.v_pointer, FALSE); } if (item == NULL) { PyErr_Print (); goto out; } PyTuple_SetItem(params, i, item); } } /* params passed to function may have extra arguments */ if (pc->extra_args) { PyObject *tuple = params; params = PySequence_Concat(tuple, pc->extra_args); Py_DECREF(tuple); } ret = PyObject_CallObject(pc->callback, params); if (ret == NULL) { if (pc->exception_handler) pc->exception_handler(return_value, n_param_values, param_values); else PyErr_Print(); goto out; } if (G_IS_VALUE(return_value) && pyg_value_from_pyobject(return_value, ret) != 0) { PyErr_SetString(PyExc_TypeError, "can't convert return value to desired type"); if (pc->exception_handler) pc->exception_handler(return_value, n_param_values, param_values); else PyErr_Print(); } Py_DECREF(ret); /* Run through the list of structs which have been passed by reference and * check if they are being held longer than the duration of the callback * execution. This is determined if the ref count is greater than 1. * A single ref is held by the argument list and any more would mean the callback * stored a ref somewhere else. In this case we make an internal copy of * the boxed struct so Python can own the memory to it. */ list_item = pass_by_ref_structs; while (list_item) { PyObject *item = list_item->data; if (item->ob_refcnt > 1) { _pygi_boxed_copy_in_place ((PyGIBoxed *)item); } list_item = g_slist_next (list_item); } out: g_slist_free (pass_by_ref_structs); Py_DECREF(params); PyGILState_Release(state); }
static gboolean peas_extension_seed_call (PeasExtensionWrapper *exten, const gchar *method_name, GIArgument *args, GIArgument *retval) { PeasExtensionSeed *sexten = PEAS_EXTENSION_SEED (exten); GType exten_type; SeedValue js_method; GICallableInfo *func_info; gint n_args, i; SeedValue *js_in_args; OutArg *out_args; SeedValue js_ret, val; SeedException exc = NULL; gchar *exc_string; gint n_in_args = 0; gint n_out_args = 0; GIArgument argument; g_return_val_if_fail (sexten->js_context != NULL, FALSE); g_return_val_if_fail (sexten->js_object != NULL, FALSE); exten_type = peas_extension_wrapper_get_extension_type (exten); /* Fetch the JS method we want to call */ js_method = seed_object_get_property (sexten->js_context, sexten->js_object, method_name); if (seed_value_is_undefined (sexten->js_context, js_method)) { g_warning ("Method '%s.%s' is not defined", g_type_name (exten_type), method_name); return FALSE; } /* We want to display an error if the method is defined but is not a function. */ if (!seed_value_is_function (sexten->js_context, js_method)) { g_warning ("Method '%s.%s' is not a function", g_type_name (exten_type), method_name); return FALSE; } /* Prepare the arguments */ func_info = peas_gi_get_method_info (exten_type, method_name); if (func_info == NULL) return FALSE; n_args = g_callable_info_get_n_args (func_info); g_return_val_if_fail (n_args >= 0, FALSE); js_in_args = g_newa (SeedValue, n_args); out_args = g_newa (OutArg, n_args + 1); /* We put the return value first in the out tuple, as it seems to be * the common behaviour for GI-based bindings */ g_callable_info_load_return_type (func_info, &out_args[0].type_info); if (g_type_info_get_tag (&out_args[0].type_info) != GI_TYPE_TAG_VOID) out_args[n_out_args++].ptr = &retval->v_pointer; /* Handle the other arguments */ for (i = 0; i < n_args && exc == NULL; i++) { GIArgInfo arg_info; GIDirection direction; g_callable_info_load_arg (func_info, i, &arg_info); direction = g_arg_info_get_direction (&arg_info); g_arg_info_load_type (&arg_info, &out_args[n_out_args].type_info); if (direction == GI_DIRECTION_IN) { js_in_args[n_in_args++] = seed_value_from_gi_argument (sexten->js_context, &args[i], &out_args[n_out_args].type_info, &exc); } if (direction == GI_DIRECTION_INOUT) { GIArgument arg; peas_gi_pointer_to_argument (&out_args[n_out_args].type_info, args[i].v_pointer, &arg); js_in_args[n_in_args++] = seed_value_from_gi_argument (sexten->js_context, &arg, &out_args[n_out_args].type_info, &exc); } if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) out_args[n_out_args++].ptr = args[i].v_pointer; } if (exc != NULL) goto cleanup; js_ret = seed_object_call (sexten->js_context, js_method, sexten->js_object, n_in_args, js_in_args, &exc); if (exc != NULL) goto cleanup; if (n_out_args == 1) { if (seed_value_to_gi_argument (sexten->js_context, js_ret, &out_args[0].type_info, &argument, &exc)) { peas_gi_argument_to_pointer (&out_args[0].type_info, &argument, out_args[0].ptr); } } else if (n_out_args > 0 && seed_value_is_object (sexten->js_context, js_ret)) { for (i = 0; i < n_out_args && exc == NULL; i++) { val = seed_object_get_property_at_index (sexten->js_context, js_ret, i, exc); if (exc == NULL && seed_value_to_gi_argument (sexten->js_context, val, &out_args[i].type_info, &argument, &exc)) { peas_gi_argument_to_pointer (&out_args[i].type_info, &argument, out_args[i].ptr); } } } cleanup: g_base_info_unref ((GIBaseInfo *) func_info); if (exc == NULL) return TRUE; exc_string = seed_exception_to_string (sexten->js_context, exc); g_warning ("Seed Exception: %s", exc_string); g_free (exc_string); return FALSE; }
void peas_gi_valist_to_arguments (GICallableInfo *callable_info, va_list va_args, GIArgument *arguments, gpointer *return_value) { gint i, n_args; GIArgInfo arg_info; GITypeInfo arg_type_info; GITypeInfo retval_info; GIArgument *cur_arg; g_return_if_fail (callable_info != NULL); n_args = g_callable_info_get_n_args (callable_info); for (i = 0; i < n_args; i++) { g_callable_info_load_arg (callable_info, i, &arg_info); g_arg_info_load_type (&arg_info, &arg_type_info); cur_arg = &arguments[i]; switch (g_arg_info_get_direction (&arg_info)) { case GI_DIRECTION_IN: { /* Notes: According to GCC 4.4, * - int8, uint8, int16, uint16, short and ushort are promoted to int when passed through '...' * - float is promoted to double when passed through '...' */ switch (g_type_info_get_tag (&arg_type_info)) { case GI_TYPE_TAG_VOID: cur_arg->v_pointer = va_arg (va_args, gpointer); break; case GI_TYPE_TAG_BOOLEAN: cur_arg->v_boolean = va_arg (va_args, gboolean); break; case GI_TYPE_TAG_INT8: cur_arg->v_int8 = va_arg (va_args, gint); break; case GI_TYPE_TAG_UINT8: cur_arg->v_uint8 = va_arg (va_args, gint); break; case GI_TYPE_TAG_INT16: cur_arg->v_int16 = va_arg (va_args, gint); break; case GI_TYPE_TAG_UINT16: cur_arg->v_uint16 = va_arg (va_args, gint); break; case GI_TYPE_TAG_INT32: cur_arg->v_int32 = va_arg (va_args, gint32); break; case GI_TYPE_TAG_UNICHAR: case GI_TYPE_TAG_UINT32: cur_arg->v_uint32 = va_arg (va_args, guint32); break; case GI_TYPE_TAG_INT64: cur_arg->v_int64 = va_arg (va_args, gint64); break; case GI_TYPE_TAG_UINT64: cur_arg->v_uint64 = va_arg (va_args, guint64); break; case GI_TYPE_TAG_FLOAT: cur_arg->v_float = va_arg (va_args, gdouble); break; case GI_TYPE_TAG_DOUBLE: cur_arg->v_double = va_arg (va_args, gdouble); break; case GI_TYPE_TAG_GTYPE: /* apparently, GType is meant to be a gsize, from gobject/gtype.h in glib */ cur_arg->v_size = va_arg (va_args, GType); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: cur_arg->v_string = va_arg (va_args, gchar *); break; case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_INTERFACE: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_ERROR: cur_arg->v_pointer = va_arg (va_args, gpointer); break; default: g_warn_if_reached (); cur_arg->v_pointer = va_arg (va_args, gpointer); break; } break; } /* In the other cases, we expect we will always have a pointer. */ case GI_DIRECTION_INOUT: case GI_DIRECTION_OUT: cur_arg->v_pointer = va_arg (va_args, gpointer); break; } } if (return_value != NULL) { g_callable_info_load_return_type (callable_info, &retval_info); if (g_type_info_get_tag (&retval_info) != GI_TYPE_TAG_VOID) *return_value = va_arg (va_args, gpointer); else *return_value = NULL; } }