123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998 |
- @c -*-texinfo-*-
- @c This is part of the GNU Guile Reference Manual.
- @c Copyright (C) 1996, 1997, 2000-2004, 2007-2014, 2016-2017
- @c Free Software Foundation, Inc.
- @c See the file guile.texi for copying conditions.
- @node Foreign Function Interface
- @section Foreign Function Interface
- @cindex foreign function interface
- @cindex ffi
- The more one hacks in Scheme, the more one realizes that there are
- actually two computational worlds: one which is warm and alive, that
- land of parentheses, and one cold and dead, the land of C and its ilk.
- But yet we as programmers live in both worlds, and Guile itself is half
- implemented in C. So it is that Guile's living half pays respect to its
- dead counterpart, via a spectrum of interfaces to C ranging from dynamic
- loading of Scheme primitives to dynamic binding of stock C library
- procedures.
- @menu
- * Foreign Libraries:: Dynamically linking to libraries.
- * Foreign Functions:: Simple calls to C procedures.
- * C Extensions:: Extending Guile in C with loadable modules.
- * Modules and Extensions:: Loading C extensions into modules.
- * Foreign Pointers:: Accessing global variables.
- * Dynamic FFI:: Calling arbitrary C functions.
- @end menu
- @node Foreign Libraries
- @subsection Foreign Libraries
- Most modern Unices have something called @dfn{shared libraries}. This
- ordinarily means that they have the capability to share the executable
- image of a library between several running programs to save memory and
- disk space. But generally, shared libraries give a lot of additional
- flexibility compared to the traditional static libraries. In fact,
- calling them `dynamic' libraries is as correct as calling them `shared'.
- Shared libraries really give you a lot of flexibility in addition to the
- memory and disk space savings. When you link a program against a shared
- library, that library is not closely incorporated into the final
- executable. Instead, the executable of your program only contains
- enough information to find the needed shared libraries when the program
- is actually run. Only then, when the program is starting, is the final
- step of the linking process performed. This means that you need not
- recompile all programs when you install a new, only slightly modified
- version of a shared library. The programs will pick up the changes
- automatically the next time they are run.
- Now, when all the necessary machinery is there to perform part of the
- linking at run-time, why not take the next step and allow the programmer
- to explicitly take advantage of it from within their program? Of course,
- many operating systems that support shared libraries do just that, and
- chances are that Guile will allow you to access this feature from within
- your Scheme programs. As you might have guessed already, this feature
- is called @dfn{dynamic linking}.@footnote{Some people also refer to the
- final linking stage at program startup as `dynamic linking', so if you
- want to make yourself perfectly clear, it is probably best to use the
- more technical term @dfn{dlopening}, as suggested by Gordon Matzigkeit
- in his libtool documentation.}
- We titled this section ``foreign libraries'' because although the name
- ``foreign'' doesn't leak into the API, the world of C really is foreign
- to Scheme -- and that estrangement extends to components of foreign
- libraries as well, as we see in future sections.
- @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
- Scheme object suitable for representing the linked object file.
- Otherwise an error is thrown. How object files are searched is system
- 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}.
- @var{library} should not contain an extension such as @code{.so}. The
- correct file name extension for the host operating system is provided
- automatically, according to libltdl's rules (@pxref{Libltdl interface,
- lt_dlopenext, @code{lt_dlopenext}, libtool, Shared Library Support for
- GNU}).
- 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.
- Note that on hosts that use dynamic-link libraries (DLLs), the global
- symbol handle may not be able to provide access to symbols from
- recursively-loaded DLLs. Only exported symbols from those DLLs directly
- loaded by the program may be available.
- @end deffn
- @deffn {Scheme Procedure} dynamic-object? obj
- @deffnx {C Function} scm_dynamic_object_p (obj)
- Return @code{#t} if @var{obj} is a dynamic library handle, or @code{#f}
- otherwise.
- @end deffn
- @deffn {Scheme Procedure} dynamic-unlink dobj
- @deffnx {C Function} scm_dynamic_unlink (dobj)
- Unlink the indicated object file from the application. The
- argument @var{dobj} must have been obtained by a call to
- @code{dynamic-link}. After @code{dynamic-unlink} has been
- called on @var{dobj}, its content is no longer accessible.
- @end deffn
- @smallexample
- (define libgl-obj (dynamic-link "libGL"))
- libgl-obj
- @result{} #<dynamic-object "libGL">
- (dynamic-unlink libGL-obj)
- libGL-obj
- @result{} #<dynamic-object "libGL" (unlinked)>
- @end smallexample
- As you can see, after calling @code{dynamic-unlink} on a dynamically
- linked library, it is marked as @samp{(unlinked)} and you are no longer
- able to use it with @code{dynamic-call}, etc. Whether the library is
- really removed from you program is system-dependent and will generally
- not happen when some other parts of your program still use it.
- When dynamic linking is disabled or not supported on your system,
- the above functions throw errors, but they are still available.
- @node Foreign Functions
- @subsection Foreign Functions
- The most natural thing to do with a dynamic library is to grovel around
- in it for a function pointer: a @dfn{foreign function}.
- @code{dynamic-func} exists for that purpose.
- @deffn {Scheme Procedure} dynamic-func name dobj
- @deffnx {C Function} scm_dynamic_func (name, dobj)
- Return a ``handle'' for the func @var{name} in the shared object referred to
- by @var{dobj}. The handle can be passed to @code{dynamic-call} to
- actually call the function.
- Regardless whether your C compiler prepends an underscore @samp{_} to the global
- names in a program, you should @strong{not} include this underscore in
- @var{name} since it will be added automatically when necessary.
- @end deffn
- Guile has static support for calling functions with no arguments,
- @code{dynamic-call}.
- @deffn {Scheme Procedure} dynamic-call func dobj
- @deffnx {C Function} scm_dynamic_call (func, dobj)
- Call the C function indicated by @var{func} and @var{dobj}.
- The function is passed no arguments and its return value is
- ignored. When @var{function} is something returned by
- @code{dynamic-func}, call that function and ignore @var{dobj}.
- When @var{func} is a string , look it up in @var{dynobj}; this
- is equivalent to
- @smallexample
- (dynamic-call (dynamic-func @var{func} @var{dobj}) #f)
- @end smallexample
- @end deffn
- @code{dynamic-call} is not very powerful. It is mostly intended to be
- used for calling specially written initialization functions that will
- then add new primitives to Guile. For example, we do not expect that you
- will dynamically link @file{libX11} with @code{dynamic-link} and then
- construct a beautiful graphical user interface just by using
- @code{dynamic-call}. Instead, the usual way would be to write a special
- Guile-to-X11 glue library that has intimate knowledge about both Guile
- and X11 and does whatever is necessary to make them inter-operate
- smoothly. This glue library could then be dynamically linked into a
- vanilla Guile interpreter and activated by calling its initialization
- function. That function would add all the new types and primitives to
- the Guile interpreter that it has to offer.
- (There is actually another, better option: simply to create a
- @file{libX11} wrapper in Scheme via the dynamic FFI. @xref{Dynamic FFI},
- for more information.)
- Given some set of C extensions to Guile, the next logical step is to
- integrate these glue libraries into the module system of Guile so that
- you can load new primitives into a running system just as you can load
- new Scheme code.
- @deffn {Scheme Procedure} load-extension lib init
- @deffnx {C Function} scm_load_extension (lib, init)
- Load and initialize the extension designated by LIB and INIT.
- When there is no pre-registered function for LIB/INIT, this is
- equivalent to
- @lisp
- (dynamic-call INIT (dynamic-link LIB))
- @end lisp
- When there is a pre-registered function, that function is called
- instead.
- Normally, there is no pre-registered function. This option exists
- only for situations where dynamic linking is unavailable or unwanted.
- In that case, you would statically link your program with the desired
- library, and register its init function right after Guile has been
- initialized.
- As for @code{dynamic-link}, @var{lib} should not contain any suffix such
- as @code{.so} (@pxref{Foreign Libraries, dynamic-link}). It
- should also not contain any directory components. Libraries that
- implement Guile Extensions should be put into the normal locations for
- shared libraries. We recommend to use the naming convention
- @file{libguile-bla-blum} for a extension related to a module @code{(bla
- blum)}.
- The normal way for a extension to be used is to write a small Scheme
- file that defines a module, and to load the extension into this
- module. When the module is auto-loaded, the extension is loaded as
- well. For example,
- @lisp
- (define-module (bla blum))
- (load-extension "libguile-bla-blum" "bla_init_blum")
- @end lisp
- @end deffn
- @node C Extensions
- @subsection C Extensions
- The most interesting application of dynamically linked libraries is
- probably to use them for providing @emph{compiled code modules} to
- Scheme programs. As much fun as programming in Scheme is, every now and
- then comes the need to write some low-level C stuff to make Scheme even
- more fun.
- Not only can you put these new primitives into their own module (see the
- previous section), you can even put them into a shared library that is
- only then linked to your running Guile image when it is actually
- needed.
- An example will hopefully make everything clear. Suppose we want to
- make the Bessel functions of the C library available to Scheme in the
- module @samp{(math bessel)}. First we need to write the appropriate
- glue code to convert the arguments and return values of the functions
- from Scheme to C and back. Additionally, we need a function that will
- add them to the set of Guile primitives. Because this is just an
- example, we will only implement this for the @code{j0} function.
- @smallexample
- #include <math.h>
- #include <libguile.h>
- SCM
- j0_wrapper (SCM x)
- @{
- return scm_from_double (j0 (scm_to_double (x, "j0")));
- @}
- void
- init_math_bessel ()
- @{
- scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper);
- @}
- @end smallexample
- We can already try to bring this into action by manually calling the low
- level functions for performing dynamic linking. The C source file needs
- to be compiled into a shared library. Here is how to do it on
- GNU/Linux, please refer to the @code{libtool} documentation for how to
- create dynamically linkable libraries portably.
- @smallexample
- gcc -shared -o libbessel.so -fPIC bessel.c
- @end smallexample
- Now fire up Guile:
- @lisp
- (define bessel-lib (dynamic-link "./libbessel.so"))
- (dynamic-call "init_math_bessel" bessel-lib)
- (j0 2)
- @result{} 0.223890779141236
- @end lisp
- The filename @file{./libbessel.so} should be pointing to the shared
- library produced with the @code{gcc} command above, of course. The
- second line of the Guile interaction will call the
- @code{init_math_bessel} function which in turn will register the C
- function @code{j0_wrapper} with the Guile interpreter under the name
- @code{j0}. This function becomes immediately available and we can call
- it from Scheme.
- Fun, isn't it? But we are only half way there. This is what
- @code{apropos} has to say about @code{j0}:
- @smallexample
- (apropos "j0")
- @print{} (guile-user): j0 #<primitive-procedure j0>
- @end smallexample
- As you can see, @code{j0} is contained in the root module, where all
- the other Guile primitives like @code{display}, etc live. In general,
- a primitive is put into whatever module is the @dfn{current module} at
- the time @code{scm_c_define_gsubr} is called.
- A compiled module should have a specially named @dfn{module init
- function}. Guile knows about this special name and will call that
- function automatically after having linked in the shared library. For
- our example, we replace @code{init_math_bessel} with the following code in
- @file{bessel.c}:
- @smallexample
- void
- init_math_bessel (void *unused)
- @{
- scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper);
- scm_c_export ("j0", NULL);
- @}
- void
- scm_init_math_bessel_module ()
- @{
- scm_c_define_module ("math bessel", init_math_bessel, NULL);
- @}
- @end smallexample
- The general pattern for the name of a module init function is:
- @samp{scm_init_}, followed by the name of the module where the
- individual hierarchical components are concatenated with underscores,
- followed by @samp{_module}.
- After @file{libbessel.so} has been rebuilt, we need to place the shared
- library into the right place.
- Once the module has been correctly installed, it should be possible to
- use it like this:
- @smallexample
- guile> (load-extension "./libbessel.so" "scm_init_math_bessel_module")
- guile> (use-modules (math bessel))
- guile> (j0 2)
- 0.223890779141236
- guile> (apropos "j0")
- @print{} (math bessel): j0 #<primitive-procedure j0>
- @end smallexample
- That's it!
- @node Modules and Extensions
- @subsection Modules and Extensions
- The new primitives that you add 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. Extensions loaded from the REPL,
- for example, will be placed into the @code{(guile-user)} module, if the
- REPL module was not changed.
- To define C primitives within a specific module, the simplest way is:
- @example
- (define-module (foo bar))
- (load-extension "foobar-c-code" "foo_bar_init")
- @end example
- @cindex extensiondir
- When loaded with @code{(use-modules (foo bar))}, the
- @code{load-extension} call looks for the @file{foobar-c-code.so} (etc)
- object file in Guile's @code{extensiondir}, which is usually a
- subdirectory of the @code{libdir}. For example, if your libdir is
- @file{/usr/lib}, the @code{extensiondir} for the Guile @value{EFFECTIVE-VERSION}.@var{x}
- series will be @file{/usr/lib/guile/@value{EFFECTIVE-VERSION}/}.
- The extension path includes the major and minor version of Guile (the
- ``effective version''), because Guile guarantees compatibility within a
- given effective version. This allows you to install different versions
- of the same extension for different versions of Guile.
- If the extension is not found in the @code{extensiondir}, Guile will
- also search the standard system locations, such as @file{/usr/lib} or
- @file{/usr/local/lib}. It is preferable, however, to keep your extension
- out of the system library path, to prevent unintended interference with
- other dynamically-linked C libraries.
- If someone installs your module to a non-standard location then the
- object file won't be found. You can address this by inserting the
- install location in the @file{foo/bar.scm} file. This is convenient
- for the user and also guarantees the intended object is read, even if
- stray older or newer versions are in the loader's path.
- The usual way to specify an install location is with a @code{prefix}
- at the configure stage, for instance @samp{./configure prefix=/opt}
- results in library files as say @file{/opt/lib/foobar-c-code.so}.
- When using Autoconf (@pxref{Top, , Introduction, autoconf, The GNU
- Autoconf Manual}), the library location is in a @code{libdir}
- variable. Its value is intended to be expanded by @command{make}, and
- can by substituted into a source file like @file{foo.scm.in}
- @example
- (define-module (foo bar))
- (load-extension "XXextensiondirXX/foobar-c-code" "foo_bar_init")
- @end example
- @noindent
- with the following in a @file{Makefile}, using @command{sed}
- (@pxref{Top, , Introduction, sed, SED, A Stream Editor}),
- @example
- foo.scm: foo.scm.in
- sed 's|XXextensiondirXX|$(libdir)/guile/@value{EFFECTIVE-VERSION}|' <foo.scm.in >foo.scm
- @end example
- The actual pattern @code{XXextensiondirXX} is arbitrary, it's only something
- which doesn't otherwise occur. If several modules need the value, it
- can be easier to create one @file{foo/config.scm} with a define of the
- @code{extensiondir} location, and use that as required.
- @example
- (define-module (foo config))
- (define-public foo-config-extensiondir "XXextensiondirXX"")
- @end example
- Such a file might have other locations too, for instance a data
- directory for auxiliary files, or @code{localedir} if the module has
- its own @code{gettext} message catalogue
- (@pxref{Internationalization}).
- It will be noted all of the above requires that the Scheme code to be
- found in @code{%load-path} (@pxref{Load Paths}). Presently it's left up
- to the system administrator or each user to augment that path when
- installing Guile modules in non-default locations. But having reached
- the Scheme code, that code should take care of hitting any of its own
- private files etc.
- @node Foreign Pointers
- @subsection Foreign Pointers
- The previous sections have shown how Guile can be extended at runtime by
- loading compiled C extensions. This approach is all well and good, but
- wouldn't it be nice if we didn't have to write any C at all? This
- section takes up the problem of accessing C values from Scheme, and the
- next discusses C functions.
- @menu
- * Foreign Types:: Expressing C types in Scheme.
- * Foreign Variables:: Pointers to C symbols.
- * Void Pointers and Byte Access:: Pointers into the ether.
- * Foreign Structs:: Packing and unpacking structs.
- @end menu
- @node Foreign Types
- @subsubsection Foreign Types
- The first impedance mismatch that one sees between C and Scheme is that
- in C, the storage locations (variables) are typed, but in Scheme types
- are associated with values, not variables. @xref{Values and Variables}.
- So when describing a C function or a C structure so that it can be
- accessed from Scheme, the data types of the parameters or fields must be
- passed explicitly.
- These ``C type values'' may be constructed using the constants and
- procedures from the @code{(system foreign)} module, which may be loaded
- like this:
- @example
- (use-modules (system foreign))
- @end example
- @code{(system foreign)} exports a number of values expressing the basic
- C types:
- @defvr {Scheme Variable} int8
- @defvrx {Scheme Variable} uint8
- @defvrx {Scheme Variable} uint16
- @defvrx {Scheme Variable} int16
- @defvrx {Scheme Variable} uint32
- @defvrx {Scheme Variable} int32
- @defvrx {Scheme Variable} uint64
- @defvrx {Scheme Variable} int64
- @defvrx {Scheme Variable} float
- @defvrx {Scheme Variable} double
- These values represent the C numeric types of the specified sizes and
- signednesses.
- @end defvr
- In addition there are some convenience bindings for indicating types of
- platform-dependent size:
- @defvr {Scheme Variable} int
- @defvrx {Scheme Variable} unsigned-int
- @defvrx {Scheme Variable} long
- @defvrx {Scheme Variable} unsigned-long
- @defvrx {Scheme Variable} size_t
- @defvrx {Scheme Variable} ssize_t
- @defvrx {Scheme Variable} ptrdiff_t
- Values exported by the @code{(system foreign)} module, representing C
- numeric types. For example, @code{long} may be @code{equal?} to
- @code{int64} on a 64-bit platform.
- @end defvr
- @defvr {Scheme Variable} void
- The @code{void} type. It can be used as the first argument to
- @code{pointer->procedure} to wrap a C function that returns nothing.
- @end defvr
- In addition, the symbol @code{*} is used by convention to denote pointer
- types. Procedures detailed in the following sections, such as
- @code{pointer->procedure}, accept it as a type descriptor.
- @node Foreign Variables
- @subsubsection Foreign Variables
- Pointers to variables in the current address space may be looked up
- dynamically using @code{dynamic-pointer}.
- @deffn {Scheme Procedure} dynamic-pointer name dobj
- @deffnx {C Function} scm_dynamic_pointer (name, dobj)
- Return a ``wrapped pointer'' for the symbol @var{name} in the shared
- object referred to by @var{dobj}. The returned pointer points to a C
- object.
- Regardless whether your C compiler prepends an underscore @samp{_} to the global
- names in a program, you should @strong{not} include this underscore in
- @var{name} since it will be added automatically when necessary.
- @end deffn
- For example, currently Guile has a variable, @code{scm_numptob}, as part
- of its API. It is declared as a C @code{long}. So, to create a handle
- pointing to that foreign value, we do:
- @example
- (use-modules (system foreign))
- (define numptob (dynamic-pointer "scm_numptob" (dynamic-link)))
- numptob
- @result{} #<pointer 0x7fb35b1b4688>
- @end example
- (The next section discusses ways to dereference pointers.)
- A value returned by @code{dynamic-pointer} is a Scheme wrapper for a C
- pointer.
- @deffn {Scheme Procedure} pointer-address pointer
- @deffnx {C Function} scm_pointer_address (pointer)
- Return the numerical value of @var{pointer}.
- @example
- (pointer-address numptob)
- @result{} 139984413364296 ; YMMV
- @end example
- @end deffn
- @deffn {Scheme Procedure} make-pointer address [finalizer]
- Return a foreign pointer object pointing to @var{address}. If
- @var{finalizer} is passed, it should be a pointer to a one-argument C
- function that will be called when the pointer object becomes
- unreachable.
- @end deffn
- @deffn {Scheme Procedure} pointer? obj
- Return @code{#t} if @var{obj} is a pointer object, @code{#f} otherwise.
- @end deffn
- @defvr {Scheme Variable} %null-pointer
- A foreign pointer whose value is 0.
- @end defvr
- @deffn {Scheme Procedure} null-pointer? pointer
- Return @code{#t} if @var{pointer} is the null pointer, @code{#f} otherwise.
- @end deffn
- For the purpose of passing SCM values directly to foreign functions, and
- allowing them to return SCM values, Guile also supports some unsafe
- casting operators.
- @deffn {Scheme Procedure} scm->pointer scm
- Return a foreign pointer object with the @code{object-address}
- of @var{scm}.
- @end deffn
- @deffn {Scheme Procedure} pointer->scm pointer
- Unsafely cast @var{pointer} to a Scheme object.
- Cross your fingers!
- @end deffn
- Sometimes you want to give C extensions access to the dynamic FFI. At
- that point, the names get confusing, because ``pointer'' can refer to a
- @code{SCM} object that wraps a pointer, or to a @code{void*} value. We
- will try to use ``pointer object'' to refer to Scheme objects, and
- ``pointer value'' to refer to @code{void *} values.
- @deftypefn {C Function} SCM scm_from_pointer (void *ptr, void (*finalizer) (void*))
- Create a pointer object from a pointer value.
- If @var{finalizer} is non-null, Guile arranges to call it on the pointer
- value at some point after the pointer object becomes collectable.
- @end deftypefn
- @deftypefn {C Function} void* scm_to_pointer (SCM obj)
- Unpack the pointer value from a pointer object.
- @end deftypefn
- @node Void Pointers and Byte Access
- @subsubsection Void Pointers and Byte Access
- Wrapped pointers are untyped, so they are essentially equivalent to C
- @code{void} pointers. As in C, the memory region pointed to by a
- pointer can be accessed at the byte level. This is achieved using
- @emph{bytevectors} (@pxref{Bytevectors}). The @code{(rnrs bytevectors)}
- module contains procedures that can be used to convert byte sequences to
- Scheme objects such as strings, floating point numbers, or integers.
- @deffn {Scheme Procedure} pointer->bytevector pointer len [offset [uvec_type]]
- @deffnx {C Function} scm_pointer_to_bytevector (pointer, len, offset, uvec_type)
- Return a bytevector aliasing the @var{len} bytes pointed to by
- @var{pointer}.
- The user may specify an alternate default interpretation for the memory
- by passing the @var{uvec_type} argument, to indicate that the memory is
- an array of elements of that type. @var{uvec_type} should be something
- that @code{array-type} would return, like @code{f32} or @code{s16}.
- When @var{offset} is passed, it specifies the offset in bytes relative
- to @var{pointer} of the memory region aliased by the returned
- bytevector.
- Mutating the returned bytevector mutates the memory pointed to by
- @var{pointer}, so buckle your seatbelts.
- @end deffn
- @deffn {Scheme Procedure} bytevector->pointer bv [offset]
- @deffnx {C Function} scm_bytevector_to_pointer (bv, offset)
- Return a pointer pointer aliasing the memory pointed to by @var{bv} or
- @var{offset} bytes after @var{bv} when @var{offset} is passed.
- @end deffn
- In addition to these primitives, convenience procedures are available:
- @deffn {Scheme Procedure} dereference-pointer pointer
- Assuming @var{pointer} points to a memory region that holds a pointer,
- return this pointer.
- @end deffn
- @deffn {Scheme Procedure} string->pointer string [encoding]
- Return a foreign pointer to a nul-terminated copy of @var{string} in the
- given @var{encoding}, defaulting to the current locale encoding. The C
- string is freed when the returned foreign pointer becomes unreachable.
- This is the Scheme equivalent of @code{scm_to_stringn}.
- @end deffn
- @deffn {Scheme Procedure} pointer->string pointer [length] [encoding]
- Return the string representing the C string pointed to by @var{pointer}.
- If @var{length} is omitted or @code{-1}, the string is assumed to be
- nul-terminated. Otherwise @var{length} is the number of bytes in memory
- pointed to by @var{pointer}. The C string is assumed to be in the given
- @var{encoding}, defaulting to the current locale encoding.
- This is the Scheme equivalent of @code{scm_from_stringn}.
- @end deffn
- @cindex wrapped pointer types
- Most object-oriented C libraries use pointers to specific data
- structures to identify objects. It is useful in such cases to reify the
- different pointer types as disjoint Scheme types. The
- @code{define-wrapped-pointer-type} macro simplifies this.
- @deffn {Scheme Syntax} define-wrapped-pointer-type type-name pred wrap unwrap print
- Define helper procedures to wrap pointer objects into Scheme objects
- with a disjoint type. Specifically, this macro defines:
- @itemize
- @item @var{pred}, a predicate for the new Scheme type;
- @item @var{wrap}, a procedure that takes a pointer object and returns an
- object that satisfies @var{pred};
- @item @var{unwrap}, which does the reverse.
- @end itemize
- @var{wrap} preserves pointer identity, for two pointer objects @var{p1}
- and @var{p2} that are @code{equal?}, @code{(eq? (@var{wrap} @var{p1})
- (@var{wrap} @var{p2})) @result{} #t}.
- Finally, @var{print} should name a user-defined procedure to print such
- objects. The procedure is passed the wrapped object and a port to write
- to.
- For example, assume we are wrapping a C library that defines a type,
- @code{bottle_t}, and functions that can be passed @code{bottle_t *}
- pointers to manipulate them. We could write:
- @example
- (define-wrapped-pointer-type bottle
- bottle?
- wrap-bottle unwrap-bottle
- (lambda (b p)
- (format p "#<bottle of ~a ~x>"
- (bottle-contents b)
- (pointer-address (unwrap-bottle b)))))
- (define grab-bottle
- ;; Wrapper for `bottle_t *grab (void)'.
- (let ((grab (pointer->procedure '*
- (dynamic-func "grab_bottle" libbottle)
- '())))
- (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)
- '(*))))
- (lambda (b)
- "Return the contents of B."
- (pointer->string (contents (unwrap-bottle b))))))
- (write (grab-bottle))
- @result{} #<bottle of Ch@^ateau Haut-Brion 803d36>
- @end example
- In this example, @code{grab-bottle} is guaranteed to return a genuine
- @code{bottle} object satisfying @code{bottle?}. Likewise,
- @code{bottle-contents} errors out when its argument is not 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:
- @example
- (use-modules (rnrs bytevectors))
- (bytevector-uint-ref (pointer->bytevector numptob (sizeof long))
- 0 (native-endianness)
- (sizeof long))
- @result{} 8
- @end example
- If we wanted to corrupt Guile's internal state, we could set
- @code{scm_numptob} to another value; but we shouldn't, because that
- variable is not meant to be set. Indeed this point applies more widely:
- the C API is a dangerous place to be. Not only might setting a value
- crash your program, simply accessing the data pointed to by a dangling
- pointer or similar can prove equally disastrous.
- @node Foreign Structs
- @subsubsection Foreign Structs
- Finally, one last note on foreign values before moving on to actually
- calling foreign functions. Sometimes you need to deal with C structs,
- which requires interpreting each element of the struct according to the
- its type, offset, and alignment. Guile has some primitives to support
- this.
- @deffn {Scheme Procedure} sizeof type
- @deffnx {C Function} scm_sizeof (type)
- Return the size of @var{type}, in bytes.
- @var{type} should be a valid C type, like @code{int}.
- Alternately @var{type} may be the symbol @code{*}, in which
- case the size of a pointer is returned. @var{type} may
- also be a list of types, in which case the size of a
- @code{struct} with ABI-conventional packing is returned.
- @end deffn
- @deffn {Scheme Procedure} alignof type
- @deffnx {C Function} scm_alignof (type)
- Return the alignment of @var{type}, in bytes.
- @var{type} should be a valid C type, like @code{int}.
- Alternately @var{type} may be the symbol @code{*}, in which
- case the alignment of a pointer is returned. @var{type} may
- also be a list of types, in which case the alignment of a
- @code{struct} with ABI-conventional packing is returned.
- @end deffn
- Guile also provides some convenience methods to pack and unpack foreign
- pointers wrapping C structs.
- @deffn {Scheme Procedure} make-c-struct types vals
- Create a foreign pointer to a C struct containing @var{vals} with types
- @code{types}.
- @var{vals} and @code{types} should be lists of the same length.
- @end deffn
- @deffn {Scheme Procedure} parse-c-struct foreign types
- Parse a foreign pointer to a C struct, returning a list of values.
- @code{types} should be a list of C types.
- @end deffn
- For example, to create and parse the equivalent of a @code{struct @{
- int64_t a; uint8_t b; @}}:
- @example
- (parse-c-struct (make-c-struct (list int64 uint8)
- (list 300 43))
- (list int64 uint8))
- @result{} (300 43)
- @end example
- As yet, Guile only has convenience routines to support
- conventionally-packed structs. But given the @code{bytevector->pointer}
- and @code{pointer->bytevector} routines, one can create and parse
- tightly packed structs and unions by hand. See the code for
- @code{(system foreign)} for details.
- @node Dynamic FFI
- @subsection Dynamic FFI
- Of course, the land of C is not all nouns and no verbs: there are
- functions too, and Guile allows you to call them.
- @deffn {Scheme Procedure} pointer->procedure return_type func_ptr arg_types @
- [#:return-errno?=#f]
- @deffnx {C Function} scm_pointer_to_procedure (return_type, func_ptr, arg_types)
- @deffnx {C Function} scm_pointer_to_procedure_with_errno (return_type, func_ptr, arg_types)
- Make a foreign function.
- Given the foreign void pointer @var{func_ptr}, its argument and
- return types @var{arg_types} and @var{return_type}, return a
- procedure that will pass arguments to the foreign function
- and return appropriate values.
- @var{arg_types} should be a list of foreign types.
- @code{return_type} should be a foreign type. @xref{Foreign Types}, for
- more information on foreign types.
- If @var{return-errno?} is true, or when calling
- @code{scm_pointer_to_procedure_with_errno}, the returned procedure will
- return two values, with @code{errno} as the second value.
- @end deffn
- Here is a better definition of @code{(math bessel)}:
- @example
- (define-module (math bessel)
- #:use-module (system foreign)
- #:export (j0))
- (define libm (dynamic-link "libm"))
- (define j0
- (pointer->procedure double
- (dynamic-func "j0" libm)
- (list double)))
- @end example
- That's it! No C at all.
- Numeric arguments and return values from foreign functions are
- represented as Scheme values. For example, @code{j0} in the above
- example takes a Scheme number as its argument, and returns a Scheme
- number.
- Pointers may be passed to and returned from foreign functions as well.
- In that case the type of the argument or return value should be the
- symbol @code{*}, indicating a pointer. For example, the following
- code makes @code{memcpy} available to Scheme:
- @example
- (define memcpy
- (let ((this (dynamic-link)))
- (pointer->procedure '*
- (dynamic-func "memcpy" this)
- (list '* '* size_t))))
- @end example
- To invoke @code{memcpy}, one must pass it foreign pointers:
- @example
- (use-modules (rnrs bytevectors))
- (define src-bits
- (u8-list->bytevector '(0 1 2 3 4 5 6 7)))
- (define src
- (bytevector->pointer src-bits))
- (define dest
- (bytevector->pointer (make-bytevector 16 0)))
- (memcpy dest src (bytevector-length src-bits))
- (bytevector->u8-list (pointer->bytevector dest 16))
- @result{} (0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0)
- @end example
- One may also pass structs as values, passing structs as foreign
- pointers. @xref{Foreign Structs}, for more information on how to express
- struct types and struct values.
- ``Out'' arguments are passed as foreign pointers. The memory pointed to
- by the foreign pointer is mutated in place.
- @example
- ;; struct timeval @{
- ;; time_t tv_sec; /* seconds */
- ;; suseconds_t tv_usec; /* microseconds */
- ;; @};
- ;; assuming fields are of type "long"
- (define gettimeofday
- (let ((f (pointer->procedure
- int
- (dynamic-func "gettimeofday" (dynamic-link))
- (list '* '*)))
- (tv-type (list long long)))
- (lambda ()
- (let* ((timeval (make-c-struct tv-type (list 0 0)))
- (ret (f timeval %null-pointer)))
- (if (zero? ret)
- (apply values (parse-c-struct timeval tv-type))
- (error "gettimeofday returned an error" ret))))))
- (gettimeofday)
- @result{} 1270587589
- @result{} 499553
- @end example
- As you can see, this interface to foreign functions is at a very low,
- somewhat dangerous level@footnote{A contribution to Guile in the form of
- a high-level FFI would be most welcome.}.
- @cindex callbacks
- The FFI can also work in the opposite direction: making Scheme
- procedures callable from C. This makes it possible to use Scheme
- procedures as ``callbacks'' expected by C function.
- @deffn {Scheme Procedure} procedure->pointer return-type proc arg-types
- @deffnx {C Function} scm_procedure_to_pointer (return_type, proc, arg_types)
- Return a pointer to a C function of type @var{return-type}
- taking arguments of types @var{arg-types} (a list) and
- behaving as a proxy to procedure @var{proc}. Thus
- @var{proc}'s arity, supported argument types, and return
- type should match @var{return-type} and @var{arg-types}.
- @end deffn
- As an example, here's how the C library's @code{qsort} array sorting
- function can be made accessible to Scheme (@pxref{Array Sort Function,
- @code{qsort},, libc, The GNU C Library Reference Manual}):
- @example
- (define qsort!
- (let ((qsort (pointer->procedure void
- (dynamic-func "qsort"
- (dynamic-link))
- (list '* size_t size_t '*))))
- (lambda (bv compare)
- ;; Sort bytevector BV in-place according to comparison
- ;; procedure COMPARE.
- (let ((ptr (procedure->pointer int
- (lambda (x y)
- ;; X and Y are pointers so,
- ;; for convenience, dereference
- ;; them before calling COMPARE.
- (compare (dereference-uint8* x)
- (dereference-uint8* y)))
- (list '* '*))))
- (qsort (bytevector->pointer bv)
- (bytevector-length bv) 1 ;; we're sorting bytes
- ptr)))))
- (define (dereference-uint8* ptr)
- ;; Helper function: dereference the byte pointed to by PTR.
- (let ((b (pointer->bytevector ptr 1)))
- (bytevector-u8-ref b 0)))
- (define bv
- ;; An unsorted array of bytes.
- (u8-list->bytevector '(7 1 127 3 5 4 77 2 9 0)))
- ;; Sort BV.
- (qsort! bv (lambda (x y) (- x y)))
- ;; Let's see what the sorted array looks like:
- (bytevector->u8-list bv)
- @result{} (0 1 2 3 4 5 7 9 77 127)
- @end example
- And voil@`a!
- Note that @code{procedure->pointer} is not supported (and not defined)
- on a few exotic architectures. Thus, user code may need to check
- @code{(defined? 'procedure->pointer)}. Nevertheless, it is available on
- many architectures, including (as of libffi 3.0.9) x86, ia64, SPARC,
- PowerPC, ARM, and MIPS, to name a few.
- @c Local Variables:
- @c TeX-master: "guile.texi"
- @c End:
|