static gboolean set_out_arg (JSContext *js_context, GIFunctionInfo *func_info, gboolean is_return_value, GIArgInfo *arg_info, GITypeInfo *type_info, gpointer ptr, jsval js_value) { gboolean nullable; GITransfer transfer; GIArgument argument; GjsArgumentType arg_type; if (is_return_value) { arg_type = GJS_ARGUMENT_RETURN_VALUE; nullable = g_callable_info_may_return_null (func_info); transfer = g_callable_info_get_caller_owns (func_info); } else { arg_type = GJS_ARGUMENT_ARGUMENT; nullable = g_arg_info_may_be_null (arg_info); transfer = g_arg_info_get_ownership_transfer (arg_info); } if (!gjs_value_to_g_argument (js_context, js_value, type_info, NULL, arg_type, transfer, nullable, &argument)) { if (is_return_value) { g_warning ("Error failed to convert return value to GIArgument"); } else { g_warning ("Error failed to convert OUT argument '%s' from " "jsval to GIArgument", g_base_info_get_name (arg_info)); } return FALSE; } peas_gi_argument_to_pointer (type_info, &argument, ptr); return TRUE; }
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); }
/** * peas_extension_call_valist: (skip) * @exten: A #PeasExtension. * @method_name: the name of the method that should be called. * @args: the arguments for the method. * * Call a method of the object behind @extension, using @args as arguments. * * See peas_extension_call() for more information. * * Return value: %TRUE on successful call. * * Deprecated: 1.2. Use the dynamically implemented interface instead. */ gboolean peas_extension_call_valist (PeasExtension *exten, const gchar *method_name, va_list args) { GICallableInfo *callable_info; GITypeInfo retval_info; GIArgument *gargs; GIArgument retval; gpointer retval_ptr; gboolean ret; gint n_args; g_return_val_if_fail (PEAS_IS_EXTENSION (exten), FALSE); g_return_val_if_fail (method_name != NULL, FALSE); callable_info = peas_gi_get_method_info (peas_extension_get_extension_type (exten), method_name); /* Already warned */ if (callable_info == NULL) return FALSE; n_args = g_callable_info_get_n_args (callable_info); g_return_val_if_fail (n_args >= 0, FALSE); gargs = g_newa (GIArgument, n_args); peas_gi_valist_to_arguments (callable_info, args, gargs, &retval_ptr); ret = peas_extension_callv (exten, method_name, gargs, &retval); if (retval_ptr != NULL) { g_callable_info_load_return_type (callable_info, &retval_info); peas_gi_argument_to_pointer (&retval_info, &retval, retval_ptr); } g_base_info_unref ((GIBaseInfo *) callable_info); return ret; }
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; }