static void * _get_func(GIObjectInfo *info, SymbolGetter getter) { const char* symbol; GSList *parents = NULL, *l; GIObjectInfo *parent_info; gpointer func = NULL; parent_info = g_base_info_ref (info); while (parent_info != NULL) { parents = g_slist_prepend (parents, parent_info); parent_info = g_object_info_get_parent (parent_info); } for (l = parents; l; l = l->next) { parent_info = l->data; symbol = getter (parent_info); if (symbol == NULL) continue; g_typelib_symbol (((GIRealInfo *)parent_info)->typelib, symbol, (gpointer*) &func); if (func) break; } g_slist_free_full (parents, (GDestroyNotify) g_base_info_unref); return func; }
/** * g_function_info_invoke: (skip) * @info: a #GIFunctionInfo describing the function to invoke * @in_args: an array of #GIArgument<!-- -->s, one for each in * parameter of @info. If there are no in parameter, @in_args * can be %NULL * @n_in_args: the length of the @in_args array * @out_args: an array of #GIArgument<!-- -->s, one for each out * parameter of @info. If there are no out parameters, @out_args * may be %NULL * @n_out_args: the length of the @out_args array * @return_value: return location for the return value of the * function. If the function returns void, @return_value may be * %NULL * @error: return location for detailed error information, or %NULL * * Invokes the function described in @info with the given * arguments. Note that inout parameters must appear in both * argument lists. This function uses dlsym() to obtain a pointer * to the function, so the library or shared object containing the * described function must either be linked to the caller, or must * have been g_module_symbol()<!-- -->ed before calling this function. * * Returns: %TRUE if the function has been invoked, %FALSE if an * error occurred. */ gboolean g_function_info_invoke (GIFunctionInfo *info, const GIArgument *in_args, int n_in_args, const GIArgument *out_args, int n_out_args, GIArgument *return_value, GError **error) { const gchar *symbol; gpointer func; gboolean is_method; gboolean throws; symbol = g_function_info_get_symbol (info); if (!g_typelib_symbol (g_base_info_get_typelib((GIBaseInfo *) info), symbol, &func)) { g_set_error (error, G_INVOKE_ERROR, G_INVOKE_ERROR_SYMBOL_NOT_FOUND, "Could not locate %s: %s", symbol, g_module_error ()); return FALSE; } is_method = (g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0 && (g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0; throws = g_function_info_get_flags (info) & GI_FUNCTION_THROWS; return g_callable_info_invoke ((GICallableInfo*) info, func, in_args, n_in_args, out_args, n_out_args, return_value, is_method, throws, error); }
/** * g_function_info_prep_invoker: * @info: A #GIFunctionInfo * @invoker: Output invoker structure * @error: A #GError * * Initialize the caller-allocated @invoker structure with a cache * of information needed to invoke the C function corresponding to * @info with the platform's default ABI. * * A primary intent of this function is that a dynamic structure allocated * by a language binding could contain a #GIFunctionInvoker structure * inside the binding's function mapping. * * Returns: %TRUE on success, %FALSE otherwise with @error set. */ gboolean g_function_info_prep_invoker (GIFunctionInfo *info, GIFunctionInvoker *invoker, GError **error) { const char *symbol; ffi_type *rtype; ffi_type **atypes; GITypeInfo *tinfo; GIArgInfo *ainfo; gboolean is_method; gboolean throws; gint n_args, n_invoke_args, i; g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (invoker != NULL, FALSE); symbol = g_function_info_get_symbol ((GIFunctionInfo*) info); if (!g_typelib_symbol (g_base_info_get_typelib((GIBaseInfo *) info), symbol, &(invoker->native_address))) { g_set_error (error, G_INVOKE_ERROR, G_INVOKE_ERROR_SYMBOL_NOT_FOUND, "Could not locate %s: %s", symbol, g_module_error ()); return FALSE; } is_method = (g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0 && (g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0; throws = g_function_info_get_flags (info) & GI_FUNCTION_THROWS; tinfo = g_callable_info_get_return_type ((GICallableInfo *)info); rtype = g_type_info_get_ffi_type (tinfo); g_base_info_unref ((GIBaseInfo *)tinfo); n_args = g_callable_info_get_n_args ((GICallableInfo *)info); if (is_method) n_invoke_args = n_args+1; else n_invoke_args = n_args; if (throws) /* Add an argument for the GError */ n_invoke_args ++; /* TODO: avoid malloc here? */ atypes = g_malloc0 (sizeof (ffi_type*) * n_invoke_args); if (is_method) { atypes[0] = &ffi_type_pointer; } for (i = 0; i < n_args; i++) { int offset = (is_method ? 1 : 0); ainfo = g_callable_info_get_arg ((GICallableInfo *)info, i); switch (g_arg_info_get_direction (ainfo)) { case GI_DIRECTION_IN: tinfo = g_arg_info_get_type (ainfo); atypes[i+offset] = g_type_info_get_ffi_type (tinfo); g_base_info_unref ((GIBaseInfo *)tinfo); break; case GI_DIRECTION_OUT: case GI_DIRECTION_INOUT: atypes[i+offset] = &ffi_type_pointer; break; default: g_assert_not_reached (); } g_base_info_unref ((GIBaseInfo *)ainfo); } if (throws) { atypes[n_invoke_args - 1] = &ffi_type_pointer; } return ffi_prep_cif (&(invoker->cif), FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) == FFI_OK; }