[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] branch excise-ltdl updated: ok docs done
From: |
Andy Wingo |
Subject: |
[Guile-commits] branch excise-ltdl updated: ok docs done |
Date: |
Thu, 28 Jan 2021 11:04:33 -0500 |
This is an automated email from the git hooks/post-receive script.
wingo pushed a commit to branch excise-ltdl
in repository guile.
The following commit(s) were added to refs/heads/excise-ltdl by this push:
new bb6237f ok docs done
bb6237f is described below
commit bb6237f7bbe928047c82bf768e189badf76129b3
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Thu Jan 28 17:04:26 2021 +0100
ok docs done
---
doc/ref/api-foreign.texi | 119 +++++++++++++++++++++++++-----------------
doc/ref/guile.texi | 8 +--
module/oop/goops.scm | 2 +-
test-suite/tests/foreign.test | 36 ++++++-------
4 files changed, 92 insertions(+), 73 deletions(-)
diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi
index e834d00..b8d8781 100644
--- a/doc/ref/api-foreign.texi
+++ b/doc/ref/api-foreign.texi
@@ -83,7 +83,7 @@ implemented in the @code{(system foreign-library)} module.
[#:extensions=system-library-extensions] @
[#:search-ltdl-library-path?=#t] @
[#:search-path=search-path] @
- [#:search-system-paths?=#t]
+ [#:search-system-paths?=#t] [#:lazy?=#t] [#:global=#f]
Find the shared library denoted by @var{library} (a string or @code{#f})
and link it into the running Guile application. When everything works
out, return a Scheme object suitable for representing the linked object
@@ -113,12 +113,13 @@ environment variables:
@table @env
@item GUILE_EXTENSIONS_PATH
This is the main environment variable for users to add directories
-containing Guile extensions. The default value has no entries.
+containing Guile extensions. The default value has no entries. This
+environment variable was added in Guile 3.0.6.
@item LTDL_LIBRARY_PATH
-To implement foreign library loading, before Guile 3.0.6 Guile used
-@code{libltdl}, the dynamic library loader provided by libtool. This
-loader used @env{LTDL_LIBRARY_PATH}, and for backwards compatibility we
-still support that path.
+Before Guile 3.0.6, Guile loaded foreign libraries using @code{libltdl},
+the dynamic library loader provided by libtool. This loader used
+@env{LTDL_LIBRARY_PATH}, and for backwards compatibility we still
+support that path.
However, @code{libltdl} would not only open @code{.so} (or @code{.dll}
and so on) files, but also the @code{.la} files created by libtool. In
@@ -170,6 +171,12 @@ Falling back to the operating system for search is usually
not a great
thing; it is a recipe for making programs that work on one machine but
not on others. Still, when wrapping system libraries, it can be the
only way to get things working at all.
+
+If @var{lazy?} is true (the default), Guile will request the operating
+system to resolve symbols used by the loaded library as they are first
+used. If @var{global?} is true, symbols defined by the loaded library
+will be available when other modules need to resolve symbols; the
+default is @code{#f}, which keeps symbols local.
@end deffn
The environment variables mentioned above are parsed when the
@@ -180,12 +187,12 @@ path components, for example the three components of
@deffn {Scheme Parameter} guile-extensions-path
@deffnx {Scheme Parameter} ltdl-library-path
@deffnx {Scheme Parameter} guile-system-extensions-path
-Parameters initially bound to @env{GUILE_EXTENSIONS_PATH},
-@env{LTDL_LIBRARY_PATH}, and @env{GUILE_SYSTEM_EXTENSIONS_PATH},
-respectively. @xref{Parameters}. The current values of these
-parameters are used when building the search path when
-@code{load-foreign-library} is called, unless the caller explicitly
-passes a @code{#:search-path} argument.
+Parameters whose initial values are taken from
+@env{GUILE_EXTENSIONS_PATH}, @env{LTDL_LIBRARY_PATH}, and
+@env{GUILE_SYSTEM_EXTENSIONS_PATH}, respectively. @xref{Parameters}.
+The current values of these parameters are used when building the search
+path when @code{load-foreign-library} is called, unless the caller
+explicitly passes a @code{#:search-path} argument.
@end deffn
@deffn {Scheme Procedure} foreign-library? obj
@@ -285,15 +292,14 @@ Then your @code{(math bessel)} would import @code{(math
config)}, then
An alternate approach would be to rebind the
@code{guile-extensions-path} parameter, or its corresponding environment
-variable, but that is more useful for known site installations, as
-changing those parameters applies to other users of
-@code{load-foreign-library} as well.
+variable, but note that changing those parameters applies to other users
+of @code{load-foreign-library} as well.
Note that the new primitives that the extension adds to Guile with
@code{scm_c_define_gsubr} (@pxref{Primitive Procedures}) or with any of
the other mechanisms are placed into the module that is current when the
@code{scm_c_define_gsubr} is executed, so to be clear about what goes
-where it's best to include the @code{load-extension} in a module, as
+vwhere it's best to include the @code{load-extension} in a module, as
above. Alternately, the C code can use @code{scm_c_define_module} to
specify which module is being created:
@@ -324,14 +330,18 @@ Functions}, to skip to the good parts.
@subsection Foreign Pointers
Foreign libraries are essentially key-value mappings, where the keys are
-the names of definitions exported by the module, and the
-values are the addresses of those definitions. To look up the address
-of a definition, use @code{foreign-library-pointer}.
+names of definitions and the values are the addresses of those
+definitions. To look up the address of a definition, use
+@code{foreign-library-pointer} from the @code{(system foreign-library)}
+module.
@deffn {Scheme Procedure} foreign-library-pointer lib name
Return a ``wrapped pointer'' for the symbol @var{name} in the shared
object referred to by @var{lib}. The returned pointer points to a C
object.
+
+As a convenience, if @var{lib} is not a foreign library, it will be
+passed to @code{load-foreign-library}.
@end deffn
If we continue with the @code{bessel.so} example from before, we can get
@@ -339,8 +349,7 @@ the address of the @code{init_math_bessel} function via:
@example
(use-modules (system foreign-library))
-(define bessel (load-foreign-library "bessel"))
-(define init (foreign-library-pointer bessel init))
+(define init (foreign-library-pointer "bessel" "init_math_bessel"))
init
@result{} #<pointer 0x7fb35b1b4688>
@end example
@@ -519,20 +528,34 @@ wrapper function, joining together
@code{foreign-libary-pointer} and
@code{procedure->pointer}:
@deffn {Scheme Procedure} foreign-library-function lib name @
- return_type arg_types [#:return-errno?=#f]
+ [#:return-type=void] [#:arg-types='()] [#:return-errno?=#f]
+Load the address of @var{name} from @var{lib}, and treat it as a
+function taking arguments @var{arg-types} and returning
+@var{return-type}, optionally also with errno.
+
+An invocation of @code{foreign-library-function} is entirely equivalent
+to:
+@example
+(pointer->procedure @var{return-type}
+ (foreign-library-pointer @var{lib} @var{name})
+ @var{arg-types}
+ #:return-errno? @var{return-errno?}).
+@end example
@end deffn
-Here is a better definition of @code{(math bessel)}:
+Pulling all this together, here is a better definition of @code{(math
+bessel)}:
@example
(define-module (math bessel)
#:use-module (system foreign)
+ #:use-module (system foreign-library)
#:export (j0))
-(define libm (dynamic-link "libm"))
-
(define j0
- (foreign-library-function libm "j0" double (list double)))
+ (foreign-library-function "libm" "j0"
+ #:return-type double
+ #:arg-types (list double)))
@end example
That's it! No C at all.
@@ -646,19 +669,17 @@ pointers to manipulate them. We could write:
(define grab-bottle
;; Wrapper for `bottle_t *grab (void)'.
- (let ((grab (pointer->procedure '*
- (dynamic-func "grab_bottle" libbottle)
- '())))
+ (let ((grab (foreign-library-function libbottle "grab_bottle"
+ #:return-type '*)))
(lambda ()
"Return a new bottle."
(wrap-bottle (grab)))))
(define bottle-contents
;; Wrapper for `const char *bottle_contents (bottle_t *)'.
- (let ((contents (pointer->procedure '*
- (dynamic-func "bottle_contents"
- libbottle)
- '(*))))
+ (let ((contents (foreign-library-function libbottle "bottle_contents"
+ #:return-type '*
+ #:arg-types '(*))))
(lambda (b)
"Return the contents of B."
(pointer->string (contents (unwrap-bottle b))))))
@@ -673,12 +694,16 @@ In this example, @code{grab-bottle} is guaranteed to
return a genuine
@code{bottle} object.
@end deffn
-Going back to the @code{scm_numptob} example above, here is how we can
-read its value as a C @code{long} integer:
-
+As another example, currently Guile has a variable, @code{scm_numptob},
+as part of its API. It is declared as a C @code{long}. So, to read its
+value, we can do:
+
@example
+(use-modules (system foreign))
(use-modules (rnrs bytevectors))
-
+(define numptob
+ (foreign-library-pointer #f "scm_numptob"))
+numptob
(bytevector-uint-ref (pointer->bytevector numptob (sizeof long))
0 (native-endianness)
(sizeof long))
@@ -770,10 +795,9 @@ code makes @code{memcpy} available to Scheme:
@example
(use-modules (system foreign))
(define memcpy
- (let ((this (dynamic-link)))
- (pointer->procedure '*
- (dynamic-func "memcpy" this)
- (list '* '* size_t))))
+ (foreign-library-function #f "memcpy"
+ #:return-type '*
+ #:arg-types (list '* '* size_t)))
@end example
To invoke @code{memcpy}, one must pass it foreign pointers:
@@ -809,10 +833,9 @@ by the foreign pointer is mutated in place.
;; assuming fields are of type "long"
(define gettimeofday
- (let ((f (pointer->procedure
- int
- (dynamic-func "gettimeofday" (dynamic-link))
- (list '* '*)))
+ (let ((f (foreign-library-function #f "gettimeofday"
+ #:return-type int
+ #:arg-types (list '* '*)))
(tv-type (list long long)))
(lambda ()
(let* ((timeval (make-c-struct tv-type (list 0 0)))
@@ -850,10 +873,8 @@ function can be made accessible to Scheme (@pxref{Array
Sort Function,
@example
(define qsort!
- (let ((qsort (pointer->procedure void
- (dynamic-func "qsort"
- (dynamic-link))
- (list '* size_t size_t '*))))
+ (let ((qsort (foreign-library-function
+ #f "qsort" #:arg-types (list '* size_t size_t '*))))
(lambda (bv compare)
;; Sort bytevector BV in-place according to comparison
;; procedure COMPARE.
diff --git a/doc/ref/guile.texi b/doc/ref/guile.texi
index e924825..660b1ae 100644
--- a/doc/ref/guile.texi
+++ b/doc/ref/guile.texi
@@ -299,8 +299,6 @@ available through both Scheme and C interfaces.
* Initialization:: Initializing Guile.
* Snarfing Macros:: Macros for snarfing initialization actions.
* Data Types:: Representing values in Guile.
-* Foreign Objects:: Defining new data types in C.
-* Smobs:: Use foreign objects instead.
* Procedures:: Procedures.
* Macros:: Extending the syntax of Scheme.
* Utility Functions:: General utility functions.
@@ -314,6 +312,8 @@ available through both Scheme and C interfaces.
* Memory Management:: Memory management and garbage collection.
* Modules:: Designing reusable code libraries.
* Foreign Function Interface:: Interacting with C procedures and data.
+* Foreign Objects:: Defining new data types in C.
+* Smobs:: Use foreign objects instead.
* Scheduling:: Threads, mutexes, asyncs and dynamic roots.
* Options and Config:: Configuration, features and runtime options.
* Other Languages:: Emacs Lisp, ECMAScript, and more.
@@ -328,8 +328,6 @@ available through both Scheme and C interfaces.
@include api-init.texi
@include api-snarf.texi
@include api-data.texi
-@include api-foreign-objects.texi
-@include api-smobs.texi
@include api-procedures.texi
@include api-macros.texi
@include api-utility.texi
@@ -343,6 +341,8 @@ available through both Scheme and C interfaces.
@include api-memory.texi
@include api-modules.texi
@include api-foreign.texi
+@include api-foreign-objects.texi
+@include api-smobs.texi
@include api-scheduling.texi
@c object orientation support here
@include api-options.texi
diff --git a/module/oop/goops.scm b/module/oop/goops.scm
index d88a76b..9edc16b 100644
--- a/module/oop/goops.scm
+++ b/module/oop/goops.scm
@@ -3314,7 +3314,7 @@ var{initargs}."
;; C. However now it's a record type, though still private. Cross our
;; fingers that nobody is using it in anger!
(define <dynamic-object>
- (module-ref (resolve-module '(ice-9 dynl)) '<dynamic-object>))
+ (module-ref (resolve-module '(system foreign-library)) '<foreign-library>))
(define (define-class-subtree class)
(define! (class-name class) class)
diff --git a/test-suite/tests/foreign.test b/test-suite/tests/foreign.test
index 67b5c37..966d214 100644
--- a/test-suite/tests/foreign.test
+++ b/test-suite/tests/foreign.test
@@ -1,6 +1,6 @@
;;;; foreign.test --- FFI. -*- mode: scheme; coding: utf-8; -*-
;;;;
-;;;; Copyright (C) 2010, 2011, 2012, 2013, 2017 Free Software Foundation,
Inc.
+;;;; Copyright (C) 2010, 2011, 2012, 2013, 2017, 2021 Free Software
Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
@@ -21,6 +21,7 @@
;;;
(define-module (test-foreign)
+ #:use-module (system foreign-library)
#:use-module (system foreign)
#:use-module (rnrs bytevectors)
#:use-module (srfi srfi-1)
@@ -29,12 +30,13 @@
#:use-module (test-suite lib))
-(with-test-prefix "dynamic-pointer"
+(with-test-prefix "foreign-library-pointer"
(pass-if-exception
"error message"
- '(misc-error . "^Symbol not found")
- (dynamic-func "does_not_exist___" (dynamic-link))))
+ ;; The error comes from dlsym, which is system-dependent.
+ '(misc-error . "")
+ (foreign-library-pointer #f "does_not_exist___")))
(with-test-prefix "null pointer"
@@ -73,7 +75,7 @@
(pass-if "equal? modulo finalizer"
(let ((finalizer (false-if-exception
- (dynamic-func "scm_is_pair" (dynamic-link)))))
+ (foreign-library-pointer #f "scm_is_pair"))))
(if (not finalizer)
(throw 'unresolved) ; Windows or a static build
(equal? (make-pointer 123)
@@ -81,7 +83,7 @@
(pass-if "equal? modulo finalizer (set-pointer-finalizer!)"
(let ((finalizer (false-if-exception
- (dynamic-func "scm_is_pair" (dynamic-link))))
+ (foreign-library-pointer #f "scm_is_pair")))
(ptr (make-pointer 123)))
(if (not finalizer)
(throw 'unresolved) ; Windows or a static build
@@ -232,19 +234,15 @@
;; linking with `-export-dynamic'. Just skip these tests when it's
;; not visible.
(false-if-exception
- (pointer->procedure void
- (dynamic-func "qsort"
- (cond
- ((string-contains %host-type "cygwin")
- ;; On Cygwin, dynamic-link does
- ;; not search recursively into
- ;; linked DLLs. Thus, one needs
- ;; to link to the core C
- ;; library DLL explicitly.
- (dynamic-link "cygwin1"))
- (else
- (dynamic-link))))
- (list '* size_t size_t '*))))
+ (foreign-library-function
+ (cond
+ ((string-contains %host-type "cygwin")
+ ;; On Cygwin, load-foreign-library does not search recursively
+ ;; into linked DLLs. Thus, one needs to link to the core C
+ ;; library DLL explicitly.
+ "cygwin1")
+ (else #f))
+ "qsort" #:arg-types (list '* size_t size_t '*))))
(define (dereference-pointer-to-byte ptr)
(let ((b (pointer->bytevector ptr 1)))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Guile-commits] branch excise-ltdl updated: ok docs done,
Andy Wingo <=