builder: Turn last dlsym() function into a scope API

Looking up a get_type function by its name is now also part of
GtkBuilderScope.
This commit is contained in:
Benjamin Otte 2019-12-03 05:41:42 +01:00
parent f8a7f30a0d
commit 5015730212
4 changed files with 96 additions and 48 deletions

View File

@ -18,17 +18,17 @@
#include "config.h"
#include <string.h>
#include <gmodule.h>
#include "gtkbuilderprivate.h"
#include "gtkbuildable.h"
#include "gtkbuilderscopeprivate.h"
#include "gtkdebug.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
#include "gtkversion.h"
#include <gio/gio.h>
#include "gtkbuilderprivate.h"
#include "gtkbuilder.h"
#include "gtkbuildable.h"
#include "gtkdebug.h"
#include "gtkversion.h"
#include "gtktypebuiltins.h"
#include "gtkintl.h"
#include <string.h>
typedef struct {
@ -485,21 +485,6 @@ builder_construct (ParserData *data,
return object;
}
static GType
_get_type_by_symbol (const gchar *symbol)
{
static GModule *module = NULL;
GTypeGetFunc func;
if (!module)
module = g_module_open (NULL, 0);
if (!g_module_symbol (module, symbol, (gpointer)&func))
return G_TYPE_INVALID;
return func ();
}
static void
parse_requires (ParserData *data,
const gchar *element_name,
@ -612,7 +597,7 @@ parse_object (GtkBuildableParseContext *context,
/* Call the GType function, and return the GType, it's guaranteed afterwards
* that g_type_from_name on the name will return our GType
*/
object_type = _get_type_by_symbol (type_func);
object_type = gtk_builder_scope_get_type_from_function (gtk_builder_get_scope (data->builder), data->builder, type_func);
if (object_type == G_TYPE_INVALID)
{
g_set_error (error,

View File

@ -74,6 +74,14 @@ gtk_builder_scope_default_get_type_from_name (GtkBuilderScope *self,
return g_type_from_name (type_name);
}
static GType
gtk_builder_scope_default_get_type_from_function (GtkBuilderScope *self,
GtkBuilder *builder,
const char *type_name)
{
return G_TYPE_INVALID;
}
static GClosure *
gtk_builder_scope_default_create_closure (GtkBuilderScope *self,
GtkBuilder *builder,
@ -94,6 +102,7 @@ static void
gtk_builder_scope_default_init (GtkBuilderScopeInterface *iface)
{
iface->get_type_from_name = gtk_builder_scope_default_get_type_from_name;
iface->get_type_from_function = gtk_builder_scope_default_get_type_from_function;
iface->create_closure = gtk_builder_scope_default_create_closure;
}
@ -109,6 +118,18 @@ gtk_builder_scope_get_type_from_name (GtkBuilderScope *self,
return GTK_BUILDER_SCOPE_GET_IFACE (self)->get_type_from_name (self, builder, type_name);
}
GType
gtk_builder_scope_get_type_from_function (GtkBuilderScope *self,
GtkBuilder *builder,
const char *function_name)
{
g_return_val_if_fail (GTK_IS_BUILDER_SCOPE (self), G_TYPE_INVALID);
g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
g_return_val_if_fail (function_name != NULL, G_TYPE_INVALID);
return GTK_BUILDER_SCOPE_GET_IFACE (self)->get_type_from_function (self, builder, function_name);
}
GClosure *
gtk_builder_scope_create_closure (GtkBuilderScope *self,
GtkBuilder *builder,
@ -237,6 +258,57 @@ gtk_builder_cscope_get_type_from_name (GtkBuilderScope *scope,
return type;
}
static GCallback
gtk_builder_cscope_get_callback (GtkBuilderCScope *self,
const char *function_name,
GError **error)
{
GModule *module;
GCallback func;
func = gtk_builder_cscope_lookup_callback_symbol (self, function_name);
if (func)
return func;
module = gtk_builder_cscope_get_module (self);
if (module == NULL)
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"Could not look up function `%s`: GModule is not supported.",
function_name);
return NULL;
}
if (!g_module_symbol (module, function_name, (gpointer)&func))
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"No function named `%s`.",
function_name);
return NULL;
}
return func;
}
static GType
gtk_builder_cscope_get_type_from_function (GtkBuilderScope *scope,
GtkBuilder *builder,
const char *function_name)
{
GtkBuilderCScope *self = GTK_BUILDER_CSCOPE (scope);
GType (* type_func) (void);
type_func = (GType (*) (void)) gtk_builder_cscope_get_callback (self, function_name, NULL);
if (!type_func)
return G_TYPE_INVALID;
return type_func();
}
static GClosure *
gtk_builder_cscope_create_closure_for_funcptr (GtkBuilderCScope *self,
GtkBuilder *builder,
@ -276,35 +348,14 @@ gtk_builder_cscope_create_closure (GtkBuilderScope *scope,
GError **error)
{
GtkBuilderCScope *self = GTK_BUILDER_CSCOPE (scope);
GModule *module = gtk_builder_cscope_get_module (self);
GCallback func;
gboolean swapped;
swapped = flags & GTK_BUILDER_CLOSURE_SWAPPED;
func = gtk_builder_cscope_lookup_callback_symbol (self, function_name);
if (func)
return gtk_builder_cscope_create_closure_for_funcptr (self, builder, func, swapped, object);
if (module == NULL)
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"Could not look up function `%s`: GModule is not supported.",
function_name);
func = gtk_builder_cscope_get_callback (self, function_name, error);
if (!func)
return NULL;
}
if (!g_module_symbol (module, function_name, (gpointer)&func))
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"No function named `%s`.",
function_name);
return NULL;
}
return gtk_builder_cscope_create_closure_for_funcptr (self, builder, func, swapped, object);
}
@ -313,6 +364,7 @@ static void
gtk_builder_cscope_scope_init (GtkBuilderScopeInterface *iface)
{
iface->get_type_from_name = gtk_builder_cscope_get_type_from_name;
iface->get_type_from_function = gtk_builder_cscope_get_type_from_function;
iface->create_closure = gtk_builder_cscope_create_closure;
}

View File

@ -55,6 +55,11 @@ typedef enum {
* The C implementation will use g_type_from_name() and if that fails try to guess the
* correct function name for registering the type and then use dlsym() to load it.
* The default implementation just tries g_type_from_name() and otherwise fails.
* @get_type_from_function: Try to lookup a #GType via the given function name, specified
* explicitly in a GtkBuilder file, like via the "type-func" attribute in the "<object>" tag.
* This function is very rarely used.
* The C implementation will use dlsym() and call the resulting function as a #GTypeFunc.
* The default implementation will fail and just return %G_TYPE_INVALID.
* @create_closure: Create a closure with the given arguments. See gtk_builder_create_closure()
* for more details on those.
* The C implementation will try to use dlsym() to locate the function name and then
@ -74,6 +79,9 @@ struct _GtkBuilderScopeInterface
GType (* get_type_from_name) (GtkBuilderScope *self,
GtkBuilder *builder,
const char *type_name);
GType (* get_type_from_function) (GtkBuilderScope *self,
GtkBuilder *builder,
const char *function_name);
GClosure * (* create_closure) (GtkBuilderScope *self,
GtkBuilder *builder,

View File

@ -27,6 +27,9 @@ G_BEGIN_DECLS
GType gtk_builder_scope_get_type_from_name (GtkBuilderScope *self,
GtkBuilder *builder,
const char *type_name);
GType gtk_builder_scope_get_type_from_function(GtkBuilderScope *self,
GtkBuilder *builder,
const char *function_name);
GClosure * gtk_builder_scope_create_closure (GtkBuilderScope *self,
GtkBuilder *builder,
const char *function_name,