]> code.delx.au - gnu-emacs/commitdiff
Add portable layer for dynamic loading
authorAurélien Aptel <aurelien.aptel@gmail.com>
Sun, 15 Nov 2015 23:36:35 +0000 (00:36 +0100)
committerTed Zlatanov <tzz@lifelogs.com>
Wed, 18 Nov 2015 19:23:53 +0000 (14:23 -0500)
* src/dynlib.h: New file.
* src/dynlib.c: New file.

Co-authored-by: Philipp Stephani <phst@google.com>
src/dynlib.c [new file with mode: 0644]
src/dynlib.h [new file with mode: 0644]

diff --git a/src/dynlib.c b/src/dynlib.c
new file mode 100644 (file)
index 0000000..f947809
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *              Portable API for dynamic loading
+ *
+ *  Assuming modules are enabled on modern systems...  *Yes*, the
+ *  preprocessor macro checks could be more precise.  I don't care.
+ *
+ *  If you think the abstraction is too leaky use libltdl (libtool),
+ *  don't reinvent the wheel by fixing this one.
+ */
+
+#include "dynlib.h"
+
+/*
+ *  Windows systems
+ */
+#if defined(_WIN32)
+
+#include <windows.h>
+
+dynlib_handle_ptr dynlib_open (const char * path)
+{
+
+  return (dynlib_handle_ptr) LoadLibrary (path);
+}
+
+void * dynlib_sym (dynlib_handle_ptr h, const char * sym)
+{
+  return GetProcAddress ((HMODULE) h, sym);
+}
+
+bool dynlib_addr (void *ptr, const char **path, const char **sym)
+{
+  return false;  /* not implemented */
+}
+
+const char * dynlib_error (void)
+{
+  /* TODO: use GetLastError(), FormatMessage(), ... */
+  return "Can't load DLL";
+}
+
+int dynlib_close (dynlib_handle_ptr h)
+{
+  return FreeLibrary ((HMODULE) h) != 0;
+}
+
+
+/*
+ *  POSIX systems
+ */
+#elif defined(HAVE_UNISTD_H)
+
+#include <dlfcn.h>
+
+dynlib_handle_ptr dynlib_open (const char * path)
+{
+  return dlopen (path, RTLD_LAZY);
+}
+
+void * dynlib_sym (dynlib_handle_ptr h, const char * sym)
+{
+  return dlsym (h, sym);
+}
+
+bool dynlib_addr (void *ptr, const char **path, const char **sym)
+{
+#ifdef HAVE_DLADDR
+  Dl_info info;
+  if (dladdr (ptr, &info) != 0 && info.dli_fname != NULL && info.dli_sname != NULL)
+    {
+      *path = info.dli_fname;
+      *sym = info.dli_sname;
+      return true;
+    }
+#endif
+  return false;
+}
+
+const char * dynlib_error (void)
+{
+  return dlerror ();
+}
+
+int dynlib_close (dynlib_handle_ptr h)
+{
+  return dlclose (h) == 0;
+}
+
+#else
+
+#error "No dynamic loading for this system"
+
+#endif
diff --git a/src/dynlib.h b/src/dynlib.h
new file mode 100644 (file)
index 0000000..229fc96
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef DYNLIB_H
+#define DYNLIB_H
+
+#include <config.h>
+#include <stdbool.h>
+
+typedef void* dynlib_handle_ptr;
+dynlib_handle_ptr dynlib_open (const char * path);
+void * dynlib_sym (dynlib_handle_ptr h, const char * sym);
+bool dynlib_addr (void *ptr, const char **path, const char **sym);
+const char * dynlib_error (void);
+int dynlib_close (dynlib_handle_ptr h);
+
+#endif /* DYNLIB_H */