gobject-introspection r660 - in trunk: . girepository giscanner tools



Author: lucasr
Date: Tue Oct  7 21:25:01 2008
New Revision: 660
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=660&view=rev

Log:
2008-10-06  Lucas Rocha  <lucasr gnome org>

	Bug 555294: Add support for multiple shared libraries per typelib.

	* girepository/ginvoke.c (g_function_info_invoke),
	girepository/ginfo.c(g_registered_type_info_get_g_type): use
	g_typelib_symbol instead of g_module_symbol.
	* girepository/girepository.h: remove g_typelib_set_module and add
	g_typelib_symbol.
	* girepository/gtypelib.[ch] (find_some_symbol, _g_typelib_init,
	g_typelib_new_from_memory, g_typelib_new_from_const_memory,
	g_typelib_free, g_typelib_symbol): chnage GTypeLib to hold a list of
	modules instead of just one. The symbol lookup is now abstracted
	behind g_typelib_symbol which tries to find the passed symbol name in
	one of its modules.
	* giscanner/girwriter.py, tools/g-ir-scanner: change scanner to read
	and write shared_library attribute as a comma-separated list of libs.


Modified:
   trunk/ChangeLog
   trunk/girepository/ginfo.c
   trunk/girepository/ginvoke.c
   trunk/girepository/girepository.c
   trunk/girepository/girepository.h
   trunk/girepository/gtypelib.c
   trunk/girepository/gtypelib.h
   trunk/giscanner/girwriter.py
   trunk/tools/g-ir-scanner

Modified: trunk/girepository/ginfo.c
==============================================================================
--- trunk/girepository/ginfo.c	(original)
+++ trunk/girepository/ginfo.c	Tue Oct  7 21:25:01 2008
@@ -992,9 +992,9 @@
     return G_TYPE_NONE;
   
   get_type_func = NULL;
-  if (!g_module_symbol (((GIBaseInfo*)info)->typelib->module,
-                        type_init,
-                        (void**) &get_type_func))
+  if (!g_typelib_symbol (((GIBaseInfo*)info)->typelib,
+                         type_init,
+                         (void**) &get_type_func))
     return G_TYPE_NONE;
   
   return (* get_type_func) ();

Modified: trunk/girepository/ginvoke.c
==============================================================================
--- trunk/girepository/ginvoke.c	(original)
+++ trunk/girepository/ginvoke.c	Tue Oct  7 21:25:01 2008
@@ -162,42 +162,18 @@
   gint n_args, n_invoke_args, in_pos, out_pos, i;
   gpointer *args;
   gboolean success = FALSE;
-  
+
   symbol = g_function_info_get_symbol (info);
 
-  if (!g_module_symbol (g_base_info_get_typelib((GIBaseInfo *) info)->module,
-                        symbol, &func))
+  if (!g_typelib_symbol (g_base_info_get_typelib((GIBaseInfo *) info),
+                         symbol, &func))
     {
-      GModule *entire_app;
+      g_set_error (error,
+                   G_INVOKE_ERROR,
+                   G_INVOKE_ERROR_SYMBOL_NOT_FOUND,
+                   "Could not locate %s: %s", symbol, g_module_error ());
 
-      /*
-       * We want to be able to add symbols to an app or an auxiliary
-       * library to fill in gaps in an introspected library. However,
-       * normally we would only look for symbols in the main library
-       * (typelib->module).
-       *
-       * A more elaborate solution is probably possible, but as a
-       * simple approach for now, if we fail to find a symbol we look
-       * for it in the global module.
-       *
-       * This would not be very efficient if it happened often, since
-       * we always do the failed lookup above first, but very few
-       * symbols should be outside of typelib->module so it doesn't
-       * matter.
-       */
-      entire_app = g_module_open (NULL, 0);
-      if (!g_module_symbol (entire_app, symbol, &func))
-        {
-          g_set_error (error,
-                       G_INVOKE_ERROR,
-                       G_INVOKE_ERROR_SYMBOL_NOT_FOUND,
-                       "Could not locate %s: %s", symbol, g_module_error ());
-          
-          g_module_close (entire_app);
-          
-          return FALSE;
-        }
-      g_module_close (entire_app);
+      return FALSE;
     }
 
   is_method = (g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0

Modified: trunk/girepository/girepository.c
==============================================================================
--- trunk/girepository/girepository.c	(original)
+++ trunk/girepository/girepository.c	Tue Oct  7 21:25:01 2008
@@ -252,9 +252,6 @@
       g_hash_table_insert (repository->priv->typelibs, key, (void *)typelib);
     }
 
-  if (typelib->module == NULL)
-      typelib->module = g_module_open (NULL, 0); 
-
   return namespace;
 }
 

Modified: trunk/girepository/girepository.h
==============================================================================
--- trunk/girepository/girepository.h	(original)
+++ trunk/girepository/girepository.h	Tue Oct  7 21:25:01 2008
@@ -112,8 +112,9 @@
                                                 gsize         len);
 GTypelib *   g_typelib_new_from_mapped_file  (GMappedFile  *mfile);
 void          g_typelib_free                  (GTypelib    *typelib);
-void          g_typelib_set_module            (GTypelib    *typelib,
-                                                GModule      *module);
+gboolean      g_typelib_symbol                (GTypelib    *typelib,
+                                               const gchar *symbol_name,
+                                               gpointer    *symbol);
 const gchar * g_typelib_get_namespace         (GTypelib    *typelib);
 
 typedef enum

Modified: trunk/girepository/gtypelib.c
==============================================================================
--- trunk/girepository/gtypelib.c	(original)
+++ trunk/girepository/gtypelib.c	Tue Oct  7 21:25:01 2008
@@ -1886,44 +1886,6 @@
   return quark;
 }
 
-static const char*
-find_some_symbol (GTypelib *typelib)
-{
-  Header *header = (Header *) typelib->data;
-  gint i;
-
-  for (i = 0; i < header->n_entries; i++)
-    {
-      DirEntry *entry;
-      
-      entry = g_typelib_get_dir_entry (typelib, i + 1);
-
-      switch (entry->blob_type)
-        {
-        case BLOB_TYPE_FUNCTION:
-          {
-            FunctionBlob *blob = (FunctionBlob *) &typelib->data[entry->offset];
-            
-            if (blob->symbol)
-              return g_typelib_get_string (typelib, blob->symbol);
-          }
-          break;
-        case BLOB_TYPE_OBJECT:
-          {
-            RegisteredTypeBlob *blob = (RegisteredTypeBlob *) &typelib->data[entry->offset];
-            
-            if (blob->gtype_init)
-              return g_typelib_get_string (typelib, blob->gtype_init);
-          }
-          break;
-        default:
-          break;
-        }
-    }
-
-  return NULL;
-}
-
 static inline void
 _g_typelib_init (GTypelib *typelib)
 {
@@ -1932,76 +1894,75 @@
   header = (Header *) typelib->data;
   if (header->shared_library)
     {
-      const gchar *shlib;
+      const gchar *shlib_str;
+      GModule *app_module = NULL;
 
-      shlib = g_typelib_get_string (typelib, header->shared_library);
+      shlib_str = g_typelib_get_string (typelib, header->shared_library);
       /* note that NULL shlib means to open the main app, which is allowed */
 
-      /* If we do have a shared lib, first be sure the main app isn't already linked to it */
-      if (shlib != NULL)
+      if (shlib_str != NULL)
         {
-          const char *symbol_in_module;
-           
-          symbol_in_module = find_some_symbol (typelib);
-          if (symbol_in_module != NULL)
+          gchar **shlibs;
+          gint i;
+
+          /* shared-library is a comma-separated list of libraries */
+          shlibs = g_strsplit (shlib_str, ",", 0);
+
+          /* We load all passed libs unconditionally as if the same library is loaded
+           * again with dlopen(), the same file handle will be returned. See bug:
+           * http://bugzilla.gnome.org/show_bug.cgi?id=555294
+           */
+          for (i = 0; shlibs[i]; i++)
             {
-              typelib->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
-              if (typelib->module == NULL)
+              GModule *module;
+
+              /* Glade's autoconnect feature and OpenGL's extension mechanism
+               * as used by Clutter rely on dlopen(NULL) to work as a means of
+               * accessing the app's symbols. This keeps us from using
+               * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
+               * in general libraries are not expecting multiple copies of
+               * themselves and are not expecting to be unloaded. So we just
+               * load modules globally for now.
+               */
+
+	      module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
+
+	      if (module == NULL)
+	        {
+	          GString *shlib_full = g_string_new (shlibs[i]);
+
+	          /* Prefix with "lib", try both .la and .so */
+	          if (!g_str_has_prefix (shlib_full->str, "lib"))
+	            g_string_prepend (shlib_full, "lib");
+	          g_string_append (shlib_full, ".la");
+	          module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
+	          if (module == NULL)
+	            g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
+	          module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
+
+	          g_string_free (shlib_full, TRUE);
+	        }
+
+	      if (module == NULL)
                 {
-                  g_warning ("Could not open main app as GModule: %s",
-                             g_module_error ());
+                  g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
+                             shlibs[i], g_module_error ());
                 }
               else
                 {
-                  void *sym;
-                  if (!g_module_symbol (typelib->module, symbol_in_module, &sym))
-                    {
-                      /* we will try opening the shlib, symbol is not in app already */
-                      g_module_close (typelib->module);
-                      typelib->module = NULL;
-                    }
+                  typelib->modules = g_list_append (typelib->modules, module);
                 }
-            }
-          else
-            {
-              g_warning ("Could not find any symbols in typelib");
-            }
-        }
-     
-      if (typelib->module == NULL && shlib != NULL)
-        {
-	  GString *shlib_full;
-
-          /* Glade's autoconnect feature and OpenGL's extension mechanism
-           * as used by Clutter rely on dlopen(NULL) to work as a means of
-           * accessing the app's symbols. This keeps us from using
-           * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
-           * in general libraries are not expecting multiple copies of
-           * themselves and are not expecting to be unloaded. So we just
-           * load modules globally for now.
-           */
-
-	  typelib->module = g_module_open (shlib, G_MODULE_BIND_LAZY);
+          }
 
-	  if (typelib->module == NULL)
-	    {
-	      shlib_full = g_string_new (shlib);
-
-	      /* Prefix with "lib", try both .la and .so */
-	      if (!g_str_has_prefix (shlib_full->str, "lib"))
-		g_string_prepend (shlib_full, "lib");
-	      g_string_append (shlib_full, ".la");
-	      typelib->module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
-	      if (typelib->module == NULL)
-		g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
-	      typelib->module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
-
-	      g_string_free (shlib_full, TRUE);
-	    }
-	  if (typelib->module == NULL)
-            g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
-                       shlib, g_module_error ());
+          g_strfreev (shlibs);
         }
+
+        /* we should make sure the app_module in the end of list so that
+         * it's last symbol source when loading any symbols from modules.
+         * See comments in g_typelib_symbol */
+        app_module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+        if (app_module)
+          typelib->modules = g_list_append (typelib->modules, app_module);
     }
 }
 
@@ -2025,6 +1986,7 @@
   meta->data = memory;
   meta->len = len;
   meta->owns_memory = TRUE;
+  meta->modules = NULL;
   _g_typelib_init (meta);
   return meta;
 }
@@ -2047,6 +2009,7 @@
   meta->data = (guchar *) memory;
   meta->len = len;
   meta->owns_memory = FALSE;
+  meta->modules = NULL;
   _g_typelib_init (meta);
   return meta;
 }
@@ -2087,28 +2050,56 @@
   else
     if (typelib->owns_memory)
       g_free (typelib->data);
-  if (typelib->module)
-    g_module_close (typelib->module);
+  if (typelib->modules)
+    {
+      g_list_foreach (typelib->modules, (GFunc) g_module_close, NULL);
+      g_list_free (typelib->modules);
+    }
   g_free (typelib);
 }
 
-/**
- * g_typelib_set_module:
- * @typelib: a #GTypelib instance
- * @module: a #GModule; takes ownership of this module
- * 
- * Sets the target module for all symbols referenced by the typelib.
- **/
-void
-g_typelib_set_module (GTypelib *typelib, GModule *module)
-{
-  if (typelib->module)
-    g_module_close (typelib->module);
-  typelib->module = module;
-}
-
 const gchar *
 g_typelib_get_namespace(GTypelib *typelib)
 {
   return g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
 }
+
+/**
+ * g_typelib_symbol:
+ * @symbol_name: name of symbol to be loaded
+ * @symbol: returns a pointer to the symbol value
+ *
+ * Loads a symbol from #GTypelib.
+ *
+ * Return value: #TRUE on success
+ **/
+gboolean
+g_typelib_symbol(GTypelib *typelib, const char *symbol_name, gpointer *symbol)
+{
+  GList *l;
+
+  /*
+   * We want to be able to add symbols to an app or an auxiliary
+   * library to fill in gaps in an introspected library. However,
+   * normally we would only look for symbols in the main library
+   * (the first items in typelib->modules).
+   *
+   * A more elaborate solution is probably possible, but as a
+   * simple approach for now, if we fail to find a symbol we look
+   * for it in the global module (the last item in type->modules).
+   *
+   * This would not be very efficient if it happened often, since
+   * we always do the failed lookup above first, but very few
+   * symbols should be outside of the main libraries in
+   * typelib->modules so it doesn't matter.
+   */
+  for (l = typelib->modules; l; l = l->next)
+    {
+      GModule *module = l->data;
+
+      if (g_module_symbol (module, symbol_name, symbol))
+        return TRUE;
+    }
+
+  return FALSE;
+}

Modified: trunk/girepository/gtypelib.h
==============================================================================
--- trunk/girepository/gtypelib.h	(original)
+++ trunk/girepository/gtypelib.h	Tue Oct  7 21:25:01 2008
@@ -484,7 +484,7 @@
   gsize len;
   gboolean owns_memory;
   GMappedFile *mfile;
-  GModule *module;
+  GList *modules;
 };
 
 DirEntry *g_typelib_get_dir_entry (GTypelib *typelib,

Modified: trunk/giscanner/girwriter.py
==============================================================================
--- trunk/giscanner/girwriter.py	(original)
+++ trunk/giscanner/girwriter.py	Tue Oct  7 21:25:01 2008
@@ -31,11 +31,11 @@
 
 class GIRWriter(XMLWriter):
 
-    def __init__(self, namespace, shlib, includes):
+    def __init__(self, namespace, shlibs, includes):
         super(GIRWriter, self).__init__()
-        self._write_repository(namespace, shlib, includes)
+        self._write_repository(namespace, shlibs, includes)
 
-    def _write_repository(self, namespace, shlib, includes=set()):
+    def _write_repository(self, namespace, shlibs, includes=set()):
         attrs = [
             ('version', '1.0'),
             ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
@@ -45,15 +45,19 @@
         with self.tagcontext('repository', attrs):
             for include in includes:
                 self._write_include(include)
-            self._write_namespace(namespace, shlib)
+            self._write_namespace(namespace, shlibs)
 
     def _write_include(self, include):
         attrs = [('name', include)]
         self.write_tag('include', attrs)
 
-    def _write_namespace(self, namespace, shlib):
+    def _write_namespace(self, namespace, shlibs):
+        libraries = []
+        for l in shlibs:
+            libraries.append(os.path.basename(l))
+
         attrs = [('name', namespace.name),
-                 ('shared-library', os.path.basename(shlib))]
+                 ('shared-library', ','.join(libraries))]
         with self.tagcontext('namespace', attrs):
             for node in namespace.nodes:
                 self._write_node(node)

Modified: trunk/tools/g-ir-scanner
==============================================================================
--- trunk/tools/g-ir-scanner	(original)
+++ trunk/tools/g-ir-scanner	Tue Oct  7 21:25:01 2008
@@ -175,8 +175,8 @@
         _error("Unknown format: %s" % (options.format, ))
 
     if not options.libraries:
-        _error("Must specify --library for primary library")
-    primary_library = options.libraries[0]
+        _error("Must specify --library at least one primary library")
+    libraries = options.libraries
 
     for package in options.packages:
         output = subprocess.Popen(['pkg-config', '--cflags', package],
@@ -236,7 +236,7 @@
     namespace = glibtransformer.parse()
 
     # Write out AST
-    writer = Writer(namespace, primary_library, transformer.get_includes())
+    writer = Writer(namespace, libraries, transformer.get_includes())
     data = writer.get_xml()
     if options.output:
         fd = open(options.output, "w")



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]