]> code.delx.au - gnu-emacs/blob - src/dynlib.c
Add portable layer for dynamic loading
[gnu-emacs] / src / dynlib.c
1 /*
2 * Portable API for dynamic loading
3 *
4 * Assuming modules are enabled on modern systems... *Yes*, the
5 * preprocessor macro checks could be more precise. I don't care.
6 *
7 * If you think the abstraction is too leaky use libltdl (libtool),
8 * don't reinvent the wheel by fixing this one.
9 */
10
11 #include "dynlib.h"
12
13 /*
14 * Windows systems
15 */
16 #if defined(_WIN32)
17
18 #include <windows.h>
19
20 dynlib_handle_ptr dynlib_open (const char * path)
21 {
22
23 return (dynlib_handle_ptr) LoadLibrary (path);
24 }
25
26 void * dynlib_sym (dynlib_handle_ptr h, const char * sym)
27 {
28 return GetProcAddress ((HMODULE) h, sym);
29 }
30
31 bool dynlib_addr (void *ptr, const char **path, const char **sym)
32 {
33 return false; /* not implemented */
34 }
35
36 const char * dynlib_error (void)
37 {
38 /* TODO: use GetLastError(), FormatMessage(), ... */
39 return "Can't load DLL";
40 }
41
42 int dynlib_close (dynlib_handle_ptr h)
43 {
44 return FreeLibrary ((HMODULE) h) != 0;
45 }
46
47
48 /*
49 * POSIX systems
50 */
51 #elif defined(HAVE_UNISTD_H)
52
53 #include <dlfcn.h>
54
55 dynlib_handle_ptr dynlib_open (const char * path)
56 {
57 return dlopen (path, RTLD_LAZY);
58 }
59
60 void * dynlib_sym (dynlib_handle_ptr h, const char * sym)
61 {
62 return dlsym (h, sym);
63 }
64
65 bool dynlib_addr (void *ptr, const char **path, const char **sym)
66 {
67 #ifdef HAVE_DLADDR
68 Dl_info info;
69 if (dladdr (ptr, &info) != 0 && info.dli_fname != NULL && info.dli_sname != NULL)
70 {
71 *path = info.dli_fname;
72 *sym = info.dli_sname;
73 return true;
74 }
75 #endif
76 return false;
77 }
78
79 const char * dynlib_error (void)
80 {
81 return dlerror ();
82 }
83
84 int dynlib_close (dynlib_handle_ptr h)
85 {
86 return dlclose (h) == 0;
87 }
88
89 #else
90
91 #error "No dynamic loading for this system"
92
93 #endif