summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2010-03-17 00:51:22 +0100
committerLudovic Courtès <ludo@gnu.org>2010-03-17 00:54:01 +0100
commitd12f974b4389f11a2f5fe47f6ca786514cb3bbc9 (patch)
treecdcf0debe7eebfd49d60410509f30d570ec8f619
parentdd1464bf38c5e2dc71652b62f63e4bcf93179a14 (diff)
downloadguile-d12f974b4389f11a2f5fe47f6ca786514cb3bbc9.tar.gz
Change `dynamic-link' to return a global handle when the argument is omitted.
* libguile/dynl.c (sysdep_dynl_link): Handle FNAME == NULL. (scm_dynamic_link): Make argument optional. Adjust body accordingly. * test-suite/standalone/test-ffi (global, strerror, strlen): New bindings. Add test for these bindings. * doc/ref/api-modules.texi (Low level dynamic linking): Update description of `dynamic-link'.
-rw-r--r--doc/ref/api-modules.texi9
-rw-r--r--libguile/dynl.c36
-rwxr-xr-xtest-suite/standalone/test-ffi25
3 files changed, 61 insertions, 9 deletions
diff --git a/doc/ref/api-modules.texi b/doc/ref/api-modules.texi
index a717386b2..aa6eaa30c 100644
--- a/doc/ref/api-modules.texi
+++ b/doc/ref/api-modules.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009
+@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
@@ -1029,7 +1029,7 @@ When using the low level procedures to do your dynamic linking, you have
complete control over which library is loaded when and what gets done
with it.
-@deffn {Scheme Procedure} dynamic-link library
+@deffn {Scheme Procedure} dynamic-link [library]
@deffnx {C Function} scm_dynamic_link (library)
Find the shared library denoted by @var{library} (a string) and link it
into the running Guile application. When everything works out, return a
@@ -1040,6 +1040,11 @@ dependent.
Normally, @var{library} is just the name of some shared library file
that will be searched for in the places where shared libraries usually
reside, such as in @file{/usr/lib} and @file{/usr/local/lib}.
+
+When @var{library} is omitted, a @dfn{global symbol handle} is returned. This
+handle provides access to the symbols available to the program at run-time,
+including those exported by the program itself and the shared libraries already
+loaded.
@end deffn
@deffn {Scheme Procedure} dynamic-object? obj
diff --git a/libguile/dynl.c b/libguile/dynl.c
index 91d4ea135..a204e93d7 100644
--- a/libguile/dynl.c
+++ b/libguile/dynl.c
@@ -77,16 +77,23 @@ static void *
sysdep_dynl_link (const char *fname, const char *subr)
{
lt_dlhandle handle;
- handle = lt_dlopenext (fname);
+
+ if (fname != NULL)
+ handle = lt_dlopenext (fname);
+ else
+ /* Return a handle for the program as a whole. */
+ handle = lt_dlopen (NULL);
+
if (NULL == handle)
{
SCM fn;
SCM msg;
- fn = scm_from_locale_string (fname);
+ fn = fname != NULL ? scm_from_locale_string (fname) : SCM_BOOL_F;
msg = scm_from_locale_string (lt_dlerror ());
scm_misc_error (subr, "file: ~S, message: ~S", scm_list_2 (fn, msg));
}
+
return (void *) handle;
}
@@ -155,7 +162,7 @@ dynl_obj_print (SCM exp, SCM port, scm_print_state *pstate)
}
-SCM_DEFINE (scm_dynamic_link, "dynamic-link", 1, 0, 0,
+SCM_DEFINE (scm_dynamic_link, "dynamic-link", 0, 1, 0,
(SCM filename),
"Find the shared object (shared library) denoted by\n"
"@var{filename} and link it into the running Guile\n"
@@ -165,18 +172,33 @@ SCM_DEFINE (scm_dynamic_link, "dynamic-link", 1, 0, 0,
"Searching for object files is system dependent. Normally,\n"
"if @var{filename} does have an explicit directory it will\n"
"be searched for in locations\n"
- "such as @file{/usr/lib} and @file{/usr/local/lib}.")
+ "such as @file{/usr/lib} and @file{/usr/local/lib}.\n\n"
+ "When @var{filename} is omitted, a @dfn{global symbol handle} is\n"
+ "returned. This handle provides access to the symbols\n"
+ "available to the program at run-time, including those exported\n"
+ "by the program itself and the shared libraries already loaded.\n")
#define FUNC_NAME s_scm_dynamic_link
{
void *handle;
char *file;
scm_dynwind_begin (0);
- file = scm_to_locale_string (filename);
- scm_dynwind_free (file);
+
+ if (SCM_UNBNDP (filename))
+ file = NULL;
+ else
+ {
+ file = scm_to_locale_string (filename);
+ scm_dynwind_free (file);
+ }
+
handle = sysdep_dynl_link (file, FUNC_NAME);
scm_dynwind_end ();
- SCM_RETURN_NEWSMOB2 (scm_tc16_dynamic_obj, SCM_UNPACK (filename), handle);
+
+ SCM_RETURN_NEWSMOB2 (scm_tc16_dynamic_obj,
+ SCM_UNBNDP (filename)
+ ? SCM_UNPACK (SCM_BOOL_F) : SCM_UNPACK (filename),
+ handle);
}
#undef FUNC_NAME
diff --git a/test-suite/standalone/test-ffi b/test-suite/standalone/test-ffi
index 54876256a..19c1c1567 100755
--- a/test-suite/standalone/test-ffi
+++ b/test-suite/standalone/test-ffi
@@ -168,6 +168,31 @@ exec guile -q -s "$0" "$@"
'(0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0))
(error "unexpected dest")))
+
+;;;
+;;; Global symbols.
+;;;
+
+(use-modules ((rnrs bytevector) #:select (utf8->string)))
+
+(if (defined? 'setlocale)
+ (setlocale LC_ALL "C"))
+
+(define global (dynamic-link))
+
+(define strerror
+ (make-foreign-function '* (dynamic-func "strerror" global)
+ (list int)))
+
+(define strlen
+ (make-foreign-function size_t (dynamic-func "strlen" global)
+ (list '*)))
+
+(let* ((ptr (strerror ENOENT))
+ (len (strlen ptr))
+ (bv (foreign->bytevector ptr 'u8 0 len))
+ (str (utf8->string bv)))
+ (test #t (not (not (string-contains str "file")))))
;; Local Variables:
;; mode: scheme