guile-commits
[Top][All Lists]
Advanced

[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)))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]