Remove unused parameter from `bytevector->pointer'.
[bpt/guile.git] / libguile / dynl.c
CommitLineData
1edae076
MV
1/* dynl.c - dynamic linking
2 *
4d3526d0 3 * Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002,
e773b1e6 4 * 2003, 2008, 2009, 2010 Free Software Foundation, Inc.
1edae076 5 *
73be1d9e 6 * This library is free software; you can redistribute it and/or
53befeb7
NJ
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 3 of
9 * the License, or (at your option) any later version.
1edae076 10 *
53befeb7
NJ
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
1edae076 15 *
73be1d9e
MV
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
53befeb7
NJ
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
73be1d9e 20 */
1edae076 21
1bbd0b84
GB
22
23
dbb605f5
LC
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
27
1edae076
MV
28/* "dynl.c" dynamically link&load object files.
29 Author: Aubrey Jaffer
30 Modified for libguile by Marius Vollmer */
31
104d4533 32#if 0 /* Disabled until we know for sure that it isn't needed */
80bc7890
MV
33/* XXX - This is only here to drag in a definition of __eprintf. This
34 is needed for proper operation of dynamic linking. The real
35 solution would probably be a shared libgcc. */
36
37#undef NDEBUG
38#include <assert.h>
39
40static void
41maybe_drag_in_eprintf ()
42{
43 assert (!maybe_drag_in_eprintf);
44}
104d4533 45#endif
80bc7890 46
96599e6a 47#include <stdio.h>
13070bd3
DH
48#include <string.h>
49
a0599745 50#include "libguile/_scm.h"
eb350124 51#include "libguile/libpath.h"
a0599745
MD
52#include "libguile/dynl.h"
53#include "libguile/smob.h"
54#include "libguile/keywords.h"
55#include "libguile/ports.h"
56#include "libguile/strings.h"
a0e0793f 57#include "libguile/deprecation.h"
a0599745 58#include "libguile/validate.h"
7f9994d9 59#include "libguile/dynwind.h"
e773b1e6 60#include "libguile/foreign.h"
408ea28a 61
a8255dca 62#include <ltdl.h>
4feb69af 63
c2cbcc57
HWN
64/*
65 From the libtool manual: "Note that libltdl is not threadsafe,
66 i.e. a multithreaded application has to use a mutex for libltdl.".
67
9de87eea
MV
68 Guile does not currently support pre-emptive threads, so there is no
69 mutex. Previously SCM_CRITICAL_SECTION_START and
70 SCM_CRITICAL_SECTION_END were used: they are mentioned here in case
71 somebody is grepping for thread problems ;)
732b9327 72*/
e45947bf 73/* njrev: not threadsafe, protection needed as described above */
732b9327 74
4feb69af 75static void *
af45e3b0 76sysdep_dynl_link (const char *fname, const char *subr)
4feb69af 77{
a8255dca 78 lt_dlhandle handle;
d12f974b
LC
79
80 if (fname != NULL)
81 handle = lt_dlopenext (fname);
82 else
83 /* Return a handle for the program as a whole. */
84 handle = lt_dlopen (NULL);
85
4feb69af
MV
86 if (NULL == handle)
87 {
01449aa5
DH
88 SCM fn;
89 SCM msg;
90
d12f974b 91 fn = fname != NULL ? scm_from_locale_string (fname) : SCM_BOOL_F;
a8255dca 92 msg = scm_from_locale_string (lt_dlerror ());
1afff620 93 scm_misc_error (subr, "file: ~S, message: ~S", scm_list_2 (fn, msg));
4feb69af 94 }
d12f974b 95
4feb69af
MV
96 return (void *) handle;
97}
98
99static void
100sysdep_dynl_unlink (void *handle, const char *subr)
101{
a8255dca 102 if (lt_dlclose ((lt_dlhandle) handle))
4feb69af 103 {
a8255dca 104 scm_misc_error (subr, (char *) lt_dlerror (), SCM_EOL);
4feb69af
MV
105 }
106}
107
108static void *
52fd9639 109sysdep_dynl_value (const char *symb, void *handle, const char *subr)
4feb69af
MV
110{
111 void *fptr;
112
a8255dca 113 fptr = lt_dlsym ((lt_dlhandle) handle, symb);
4feb69af
MV
114 if (!fptr)
115 {
a8255dca 116 scm_misc_error (subr, (char *) lt_dlerror (), SCM_EOL);
4feb69af
MV
117 }
118 return fptr;
119}
120
121static void
122sysdep_dynl_init ()
123{
eb350124
AW
124 char *env;
125
a8255dca 126 lt_dlinit ();
eb350124 127
28af5ee5 128 env = getenv ("GUILE_SYSTEM_EXTENSIONS_PATH");
eb350124
AW
129 if (env && strcmp (env, "") == 0)
130 /* special-case interpret system-ltdl-path=="" as meaning no system path,
131 which is the case during the build */
132 ;
133 else if (env)
28af5ee5
AW
134 /* FIXME: should this be a colon-separated path? Or is the only point to
135 allow the build system to turn off the installed extensions path? */
eb350124 136 lt_dladdsearchdir (env);
eb350124 137 else
28af5ee5
AW
138 {
139 lt_dladdsearchdir (SCM_LIB_DIR);
140 lt_dladdsearchdir (SCM_EXTENSIONS_DIR);
141 }
4feb69af
MV
142}
143
92c2555f 144scm_t_bits scm_tc16_dynamic_obj;
80bc7890 145
f5710d53
MV
146#define DYNL_FILENAME SCM_SMOB_OBJECT
147#define DYNL_HANDLE(x) ((void *) SCM_SMOB_DATA_2 (x))
2ff08405 148#define SET_DYNL_HANDLE(x, v) (SCM_SET_SMOB_DATA_2 ((x), (scm_t_bits) (v)))
7cf1a27e 149
7cf1a27e 150
e841c3e0 151
80bc7890 152static int
e841c3e0 153dynl_obj_print (SCM exp, SCM port, scm_print_state *pstate)
80bc7890 154{
7cf1a27e
MD
155 scm_puts ("#<dynamic-object ", port);
156 scm_iprin1 (DYNL_FILENAME (exp), port, pstate);
157 if (DYNL_HANDLE (exp) == NULL)
158 scm_puts (" (unlinked)", port);
159 scm_putc ('>', port);
160 return 1;
80bc7890
MV
161}
162
8e3ab003 163
d12f974b 164SCM_DEFINE (scm_dynamic_link, "dynamic-link", 0, 1, 0,
1e6808ea 165 (SCM filename),
ee95d597
GH
166 "Find the shared object (shared library) denoted by\n"
167 "@var{filename} and link it into the running Guile\n"
168 "application. The returned\n"
169 "scheme object is a ``handle'' for the library which can\n"
170 "be passed to @code{dynamic-func}, @code{dynamic-call} etc.\n\n"
171 "Searching for object files is system dependent. Normally,\n"
172 "if @var{filename} does have an explicit directory it will\n"
173 "be searched for in locations\n"
d12f974b
LC
174 "such as @file{/usr/lib} and @file{/usr/local/lib}.\n\n"
175 "When @var{filename} is omitted, a @dfn{global symbol handle} is\n"
176 "returned. This handle provides access to the symbols\n"
177 "available to the program at run-time, including those exported\n"
178 "by the program itself and the shared libraries already loaded.\n")
1bbd0b84 179#define FUNC_NAME s_scm_dynamic_link
80bc7890 180{
7cf1a27e 181 void *handle;
7f9994d9 182 char *file;
80bc7890 183
661ae7ab 184 scm_dynwind_begin (0);
d12f974b
LC
185
186 if (SCM_UNBNDP (filename))
187 file = NULL;
188 else
189 {
190 file = scm_to_locale_string (filename);
191 scm_dynwind_free (file);
192 }
193
7f9994d9 194 handle = sysdep_dynl_link (file, FUNC_NAME);
661ae7ab 195 scm_dynwind_end ();
d12f974b
LC
196
197 SCM_RETURN_NEWSMOB2 (scm_tc16_dynamic_obj,
198 SCM_UNBNDP (filename)
199 ? SCM_UNPACK (SCM_BOOL_F) : SCM_UNPACK (filename),
200 handle);
80bc7890 201}
1bbd0b84 202#undef FUNC_NAME
80bc7890 203
80bc7890 204
a1ec6916 205SCM_DEFINE (scm_dynamic_object_p, "dynamic-object?", 1, 0, 0,
1bbd0b84 206 (SCM obj),
ee95d597
GH
207 "Return @code{#t} if @var{obj} is a dynamic object handle,\n"
208 "or @code{#f} otherwise.")
1bbd0b84 209#define FUNC_NAME s_scm_dynamic_object_p
80bc7890 210{
7888309b 211 return scm_from_bool (SCM_TYP16_PREDICATE (scm_tc16_dynamic_obj, obj));
80bc7890 212}
1bbd0b84 213#undef FUNC_NAME
80bc7890 214
b82c6ce0 215
a1ec6916 216SCM_DEFINE (scm_dynamic_unlink, "dynamic-unlink", 1, 0, 0,
1bbd0b84 217 (SCM dobj),
ee95d597
GH
218 "Unlink a dynamic object from the application, if possible. The\n"
219 "object must have been linked by @code{dynamic-link}, with \n"
220 "@var{dobj} the corresponding handle. After this procedure\n"
221 "is called, the handle can no longer be used to access the\n"
222 "object.")
1bbd0b84 223#define FUNC_NAME s_scm_dynamic_unlink
80bc7890 224{
7cf1a27e 225 /*fixme* GC-problem */
b82c6ce0
DH
226 SCM_VALIDATE_SMOB (SCM_ARG1, dobj, dynamic_obj);
227 if (DYNL_HANDLE (dobj) == NULL) {
9e375910 228 SCM_MISC_ERROR ("Already unlinked: ~S", scm_list_1 (dobj));
b82c6ce0 229 } else {
b82c6ce0
DH
230 sysdep_dynl_unlink (DYNL_HANDLE (dobj), FUNC_NAME);
231 SET_DYNL_HANDLE (dobj, NULL);
b82c6ce0
DH
232 return SCM_UNSPECIFIED;
233 }
80bc7890 234}
1bbd0b84 235#undef FUNC_NAME
80bc7890 236
b82c6ce0 237
d4149a51
LC
238SCM_DEFINE (scm_dynamic_pointer, "dynamic-pointer", 2, 0, 0,
239 (SCM name, SCM dobj),
52fd9639 240 "Return a ``handle'' for the pointer @var{name} in the\n"
ee95d597 241 "shared object referred to by @var{dobj}. The handle\n"
d4149a51 242 "aliases a C object.\n\n"
3023e7b0 243 "This facility works by asking the dynamic linker for\n"
52fd9639
AW
244 "the address of a symbol, then assuming that it aliases a\n"
245 "value of a given type. Obviously, the user must be very\n"
246 "careful to ensure that the value actually is of the\n"
247 "declared type, or bad things will happen.\n\n"
ee95d597
GH
248 "Regardless whether your C compiler prepends an underscore\n"
249 "@samp{_} to the global names in a program, you should\n"
250 "@strong{not} include this underscore in @var{name}\n"
251 "since it will be added automatically when necessary.")
52fd9639 252#define FUNC_NAME s_scm_dynamic_pointer
80bc7890 253{
52fd9639 254 void *val;
80bc7890 255
a6d9e5ab 256 SCM_VALIDATE_STRING (1, name);
d4149a51 257 SCM_VALIDATE_SMOB (SCM_ARG2, dobj, dynamic_obj);
3023e7b0
LC
258
259 if (DYNL_HANDLE (dobj) == NULL)
b82c6ce0 260 SCM_MISC_ERROR ("Already unlinked: ~S", dobj);
3023e7b0
LC
261 else
262 {
263 char *chars;
264
265 scm_dynwind_begin (0);
266 chars = scm_to_locale_string (name);
267 scm_dynwind_free (chars);
268 val = sysdep_dynl_value (chars, DYNL_HANDLE (dobj), FUNC_NAME);
269 scm_dynwind_end ();
270
5b46a8c2 271 return scm_from_pointer (val, NULL);
3023e7b0 272 }
80bc7890 273}
1bbd0b84 274#undef FUNC_NAME
80bc7890 275
b82c6ce0 276
52fd9639
AW
277SCM_DEFINE (scm_dynamic_func, "dynamic-func", 2, 0, 0,
278 (SCM name, SCM dobj),
279 "Return a ``handle'' for the function @var{name} in the\n"
280 "shared object referred to by @var{dobj}. The handle\n"
281 "can be passed to @code{dynamic-call} to actually\n"
282 "call the function.\n\n"
283 "Regardless whether your C compiler prepends an underscore\n"
284 "@samp{_} to the global names in a program, you should\n"
285 "@strong{not} include this underscore in @var{name}\n"
286 "since it will be added automatically when necessary.")
287#define FUNC_NAME s_scm_dynamic_func
288{
d4149a51 289 return scm_dynamic_pointer (name, dobj);
52fd9639
AW
290}
291#undef FUNC_NAME
292
293
a1ec6916 294SCM_DEFINE (scm_dynamic_call, "dynamic-call", 2, 0, 0,
1bbd0b84 295 (SCM func, SCM dobj),
46732b54
GH
296 "Call a C function in a dynamic object. Two styles of\n"
297 "invocation are supported:\n\n"
298 "@itemize @bullet\n"
299 "@item @var{func} can be a function handle returned by\n"
300 "@code{dynamic-func}. In this case @var{dobj} is\n"
301 "ignored\n"
302 "@item @var{func} can be a string with the name of the\n"
303 "function to call, with @var{dobj} the handle of the\n"
304 "dynamic object in which to find the function.\n"
305 "This is equivalent to\n"
306 "@smallexample\n\n"
307 "(dynamic-call (dynamic-func @var{func} @var{dobj}) #f)\n"
308 "@end smallexample\n"
309 "@end itemize\n\n"
310 "In either case, the function is passed no arguments\n"
311 "and its return value is ignored.")
1bbd0b84 312#define FUNC_NAME s_scm_dynamic_call
80bc7890 313{
5b46a8c2
LC
314 void (*fptr) (void);
315
7f9994d9 316 if (scm_is_string (func))
7cf1a27e 317 func = scm_dynamic_func (func, dobj);
5b46a8c2 318 SCM_VALIDATE_POINTER (SCM_ARG1, func);
e773b1e6 319
5b46a8c2 320 fptr = SCM_POINTER_VALUE (func);
7cf1a27e 321 fptr ();
7cf1a27e 322 return SCM_UNSPECIFIED;
80bc7890 323}
1bbd0b84 324#undef FUNC_NAME
80bc7890 325
1edae076
MV
326void
327scm_init_dynamic_linking ()
328{
7cf1a27e 329 scm_tc16_dynamic_obj = scm_make_smob_type ("dynamic-object", 0);
e841c3e0 330 scm_set_smob_print (scm_tc16_dynamic_obj, dynl_obj_print);
7cf1a27e 331 sysdep_dynl_init ();
a0599745 332#include "libguile/dynl.x"
1edae076 333}
89e00824
ML
334
335/*
336 Local Variables:
337 c-file-style: "gnu"
338 End:
339*/