[gobject-introspection] GIRepository: add API for extending library paths



commit 9faf4b4e9eac13ceb9d8c214554d5ee2a384dc28
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Fri Feb 22 01:50:48 2013 +0100

    GIRepository: add API for extending library paths
    
    Previously we would require applications that shipped with private
    typelibs to add the private path to LD_LIBRARY_PATH, or to have a
    launcher binary with the right RPATH.
    Now they can just call GIRepository.prepend_library_path() before
    they access the module.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694485

 docs/reference/gi-sections.txt    |    1 +
 girepository/girepository.h       |    1 +
 girepository/girepository.symbols |    1 +
 girepository/gitypelib.c          |   91 +++++++++++++++++++++++++++----------
 4 files changed, 70 insertions(+), 24 deletions(-)
---
diff --git a/docs/reference/gi-sections.txt b/docs/reference/gi-sections.txt
index b7565a1..8b880cf 100644
--- a/docs/reference/gi-sections.txt
+++ b/docs/reference/gi-sections.txt
@@ -7,6 +7,7 @@ GIRepositoryLoadFlags
 GITypelib
 g_irepository_get_default
 g_irepository_prepend_search_path
+g_irepository_prepend_library_path
 g_irepository_get_search_path
 g_irepository_load_typelib
 g_irepository_is_registered
diff --git a/girepository/girepository.h b/girepository/girepository.h
index eb990a2..2b2b171 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -90,6 +90,7 @@ typedef enum
 GType         g_irepository_get_type      (void) G_GNUC_CONST;
 GIRepository *g_irepository_get_default   (void);
 void          g_irepository_prepend_search_path (const char *directory);
+void          g_irepository_prepend_library_path (const char *directory);
 GSList *      g_irepository_get_search_path     (void);
 const char *  g_irepository_load_typelib  (GIRepository *repository,
                                           GITypelib     *typelib,
diff --git a/girepository/girepository.symbols b/girepository/girepository.symbols
index 8cb6c83..5f01adf 100644
--- a/girepository/girepository.symbols
+++ b/girepository/girepository.symbols
@@ -134,6 +134,7 @@ g_irepository_get_typelib_path
 g_irepository_get_version
 g_irepository_is_registered
 g_irepository_load_typelib
+g_irepository_prepend_library_path
 g_irepository_prepend_search_path
 g_irepository_require
 g_irepository_require_private
diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c
index 2af17e9..76a55de 100644
--- a/girepository/gitypelib.c
+++ b/girepository/gitypelib.c
@@ -2062,6 +2062,72 @@ g_typelib_error_quark (void)
   return quark;
 }
 
+static GSList *library_paths;
+
+/**
+ * g_irepository_prepend_library_path:
+ * @directory: (type filename): a single directory to scan for shared libraries
+ *
+ * Prepends @directory to the search path that is used to
+ * search shared libraries referenced by imported namespaces.
+ * Multiple calls to this function all contribute to the final
+ * list of paths.
+ * The list of paths is unique and shared for all #GIRepository
+ * instances across the process, but it doesn't affect namespaces
+ * imported before the call.
+ *
+ * If the library is not found in the directories configured
+ * in this way, loading will fall back to the system library
+ * path (ie. LD_LIBRARY_PATH and DT_RPATH in ELF systems).
+ * See the documentation of your dynamic linker for full details.
+ *
+ * Since: 1.35.8
+ */
+void
+g_irepository_prepend_library_path (const char *directory)
+{
+  library_paths = g_slist_prepend (library_paths,
+                                   g_strdup (directory));
+}
+
+/* Note on the GModule flags used by this function:
+
+ * Glade's autoconnect feature and OpenGL's extension mechanism
+ * as used by Clutter rely on g_module_open(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.
+ */
+static GModule *
+load_one_shared_library (const char *shlib)
+{
+  GSList *p;
+  GModule *m;
+
+  if (!g_path_is_absolute (shlib))
+    {
+      /* First try in configured library paths */
+      for (p = library_paths; p; p = p->next)
+        {
+          char *path = g_build_filename (p->data, shlib, NULL);
+
+          m = g_module_open (path, G_MODULE_BIND_LAZY);
+
+          g_free (path);
+          if (m != NULL)
+            return m;
+        }
+    }
+
+  /* Then try loading from standard paths */
+  /* Do not attempt to fix up shlib to replace .la with .so:
+     it's done by GModule anyway.
+  */
+  return g_module_open (shlib, G_MODULE_BIND_LAZY);
+}
+
 static void
 _g_typelib_do_dlopen (GITypelib *typelib)
 {
@@ -2091,30 +2157,7 @@ _g_typelib_do_dlopen (GITypelib *typelib)
         {
           GModule *module;
 
-          /* Glade's autoconnect feature and OpenGL's extension mechanism
-           * as used by Clutter rely on g_module_open(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]);
-
-              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);
-            }
+          module = load_one_shared_library (shlibs[i]);
 
           if (module == NULL)
             {


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