2 * gmodule.c: dl* functions, glib style
5 * Gonzalo Paniagua Javier (gonzalo@novell.com)
6 * Jonathan Chambers (joncham@gmail.com)
7 * Robert Jordan (robertj@gmx.net)
9 * (C) 2006 Novell, Inc.
10 * (C) 2006 Jonathan Chambers
12 * Permission is hereby granted, free of charge, to any person obtaining
13 * a copy of this software and associated documentation files (the
14 * "Software"), to deal in the Software without restriction, including
15 * without limitation the rights to use, copy, modify, merge, publish,
16 * distribute, sublicense, and/or sell copies of the Software, and to
17 * permit persons to whom the Software is furnished to do so, subject to
18 * the following conditions:
20 * The above copyright notice and this permission notice shall be
21 * included in all copies or substantial portions of the Software.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 #if defined(G_OS_UNIX) && defined(HAVE_DLFCN_H)
39 /* For Linux and Solaris, need to add others as we port this */
40 #define LIBPREFIX "lib"
41 #define LIBSUFFIX ".so"
48 g_module_open (const gchar
*file
, GModuleFlags flags
)
54 flags
&= G_MODULE_BIND_MASK
;
55 if ((flags
& G_MODULE_BIND_LAZY
) != 0)
57 if ((flags
& G_MODULE_BIND_LOCAL
) != 0)
60 handle
= dlopen (file
, f
);
64 module
= g_new (GModule
,1);
65 module
->handle
= handle
;
71 g_module_symbol (GModule
*module
, const gchar
*symbol_name
, gpointer
*symbol
)
73 if (symbol_name
== NULL
|| symbol
== NULL
)
76 if (module
== NULL
|| module
->handle
== NULL
)
79 *symbol
= dlsym (module
->handle
, symbol_name
);
80 return (*symbol
!= NULL
);
83 #if defined(HAVE_DLADDR)
85 g_module_address (void *addr
, char *file_name
, size_t file_name_len
,
86 void **file_base
, char *sym_name
, size_t sym_name_len
,
90 int ret
= dladdr(addr
, &dli
);
91 /* This zero-on-failure is unlike other Unix APIs. */
95 * AIX/Win32 return non-const, so we use caller-allocated bufs instead
97 if (file_name
!= NULL
&& file_name_len
>= 1) {
99 g_strlcpy(file_name
, dli
.dli_fname
, file_name_len
);
101 file_name
[0] = '\0';
103 if (file_base
!= NULL
)
104 *file_base
= dli
.dli_fbase
;
105 if (sym_name
!= NULL
&& sym_name_len
>= 1) {
107 g_strlcpy (sym_name
, dli
.dli_sname
, sym_name_len
);
111 if (sym_addr
!= NULL
)
112 *sym_addr
= dli
.dli_saddr
;
116 /* AIX has its own implementation that is long enough to be its own file. */
118 g_module_address (void *addr
, char *file_name
, size_t file_name_len
,
119 void **file_base
, char *sym_name
, size_t sym_name_len
,
127 g_module_error (void)
133 g_module_close (GModule
*module
)
136 if (module
== NULL
|| module
->handle
== NULL
)
139 handle
= module
->handle
;
140 module
->handle
= NULL
;
142 return (0 == dlclose (handle
));
145 #elif defined (G_OS_WIN32)
146 #ifndef PSAPI_VERSION
147 #define PSAPI_VERSION 2 // Use the Windows 7 or newer version more directly.
152 #define LIBSUFFIX ".dll"
161 g_module_open (const gchar
*file
, GModuleFlags flags
)
164 module
= g_malloc (sizeof (GModule
));
170 file16
= u8to16(file
);
171 module
->main_module
= FALSE
;
172 module
->handle
= LoadLibrary (file16
);
174 if (!module
->handle
) {
180 module
->main_module
= TRUE
;
181 module
->handle
= GetModuleHandle (NULL
);
188 w32_find_symbol (const gchar
*symbol_name
)
191 DWORD buffer_size
= sizeof (HMODULE
) * 1024;
194 modules
= (HMODULE
*) g_malloc (buffer_size
);
199 if (!EnumProcessModules (GetCurrentProcess (), modules
,
200 buffer_size
, &needed
)) {
205 /* check whether the supplied buffer was too small, realloc, retry */
206 if (needed
> buffer_size
) {
209 buffer_size
= needed
;
210 modules
= (HMODULE
*) g_malloc (buffer_size
);
215 if (!EnumProcessModules (GetCurrentProcess (), modules
,
216 buffer_size
, &needed
)) {
222 for (i
= 0; i
< needed
/ sizeof (HANDLE
); i
++) {
223 gpointer proc
= (gpointer
)(intptr_t)GetProcAddress (modules
[i
], symbol_name
);
235 g_module_symbol (GModule
*module
, const gchar
*symbol_name
, gpointer
*symbol
)
237 if (module
== NULL
|| symbol_name
== NULL
|| symbol
== NULL
)
240 if (module
->main_module
) {
241 *symbol
= (gpointer
)(intptr_t)GetProcAddress (module
->handle
, symbol_name
);
245 *symbol
= w32_find_symbol (symbol_name
);
246 return *symbol
!= NULL
;
248 *symbol
= (gpointer
)(intptr_t)GetProcAddress (module
->handle
, symbol_name
);
249 return *symbol
!= NULL
;
254 g_module_error (void)
258 DWORD code
= GetLastError ();
260 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_ALLOCATE_BUFFER
, NULL
,
261 code
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), buf
, 0, NULL
);
270 g_module_close (GModule
*module
)
275 if (module
== NULL
|| module
->handle
== NULL
)
278 handle
= module
->handle
;
279 main_module
= module
->main_module
;
280 module
->handle
= NULL
;
282 return (main_module
? 1 : (0 == FreeLibrary (handle
)));
291 g_module_open (const gchar
*file
, GModuleFlags flags
)
293 g_error ("%s", "g_module_open not implemented on this platform");
298 g_module_symbol (GModule
*module
, const gchar
*symbol_name
, gpointer
*symbol
)
300 g_error ("%s", "g_module_open not implemented on this platform");
305 g_module_error (void)
307 g_error ("%s", "g_module_open not implemented on this platform");
312 g_module_close (GModule
*module
)
314 g_error ("%s", "g_module_open not implemented on this platform");
320 g_module_build_path (const gchar
*directory
, const gchar
*module_name
)
322 const char *lib_prefix
= "";
324 if (module_name
== NULL
)
327 if (strncmp (module_name
, "lib", 3) != 0)
328 lib_prefix
= LIBPREFIX
;
330 if (directory
&& *directory
)
331 return g_strdup_printf ("%s/%s%s" LIBSUFFIX
, directory
, lib_prefix
, module_name
);
332 return g_strdup_printf ("%s%s" LIBSUFFIX
, lib_prefix
, module_name
);