The core macro foreign-call
, exported by the library
(vicare)
, is expanded to the core language syntax
foreign-call
, which in turn is compiled to code invoking a C
function from the operating system’s process image; the first argument
to foreign-call
is a string naming the C function.
Whenever the code:
(foreign-call "function_name" ?arg …)
is compiled, the C pointer referencing the entry point of the named function is retrieved with a C language call:
dlsym(RTLD_DEFAULT, "function_name");
so all the public functions from the running vicare
executable are available; also available are all the functions from
host’s shared libraries loaded with dlopen()
using the flags
RTLD_NOW | RTLD_GLOBAL
.
This API for C language functions call is meant to be used to interface with functions specifically written to be called from Scheme code; examples are interface libraries installed by the Vicare extension packages like Vicare/CURL and Vicare/SQLite. This API cannot be used to directly call a generic C language function from, say, libz.so or libgmp.so.
It is possible to associate one or more host’s shared libraries to a
FASL file, so that: whenever the FASL file is loaded, the shared
library is loaded too and the functions required by foreign-call
are available. This is especially useful to implement bindings to
foreign libraries without relying on the FFI and making full use of
garbage collection facilities and access to Scheme values’ memory
representations.
A Vicare’s library might have the format:
(library (libname) (foreign-library ?foreign-library-id) (export . ?export-specs) (import . ?import-specs) . ?body)
and a Vicare’s top–level program might have the format:
(program (progname) (foreign-library ?foreign-library-id) (import . ?import-specs) . ?body)
the ?foreign-library-id form must be a string representing the
identifier of a host’s shared object. There can be any number of
foreign-library
clauses, all before export
for
libraries and before import
for programs.
The identifier is used to build the file name of a shared object; for
example the identifier vicare-curl
is used to build the following
file names:
On Unix–like systems, including GNU+Linux.
On Darwin systems.
On Cygwin systems.
Whenever the library or program are expanded: the shared objects are
immediately loaded using dlopen()
.
Whenever a library or program in binary form is written to a FASL
file: an object field with header O
is written to the
beginning of the FASL file; such object will cause the
shared object to be dynamically loaded whenever the FASL file is
loaded.