gauche.ffi - FFI ¶This module provides the means to call compiled functions in other languages via C ABI. It allows user programs to use external libraries without writing a custom extension.
Although it is convenient, you need to keep in mind that the external libraries does not necessarily aligns Gauche’s runtime conventions, therefore you cannot rely on Gauche’s guardrails. You can easily pass arguments of incorrect types, interpret the result incorrectly, or access objects outside of its lifetime. Small mistakes can eaisly cause access violation or memory corruption.
We adopt pluggable subsystems; we have a few different FFI implementations. The system chooses one suitable for the situation, or you can specify which one ot use. Here is the list of available subsystems:
:nativeA machine-code trampoline stub is constructed at the runtime. The overhad is small, but this is architecture-dependent and only available on limited architecture (currently, x86_64 on Unix-family and MinGW. a plan to support Aarch64 in near future). This is selected by default when you’re running on the supported platform.
:stubA stub C code is generated, compiled and dyamically linked when
with-ffi form is evaluated. It incurs one-time overhead when
the compilation takes place; but once linked, calling the FFI functions
are just as fast as calling C funcitons via extension modules.
This is available on all platforms, and used as the fallback by default.
:aotA variation of :stub subsystem, used when the file including
with-ffi forms are precompiled. The stub code generation is
done at the same time of precompilation, so loading the compiled module
does not incur extra overhead. This is selected when
you precompile the file, regardless of the underlying architecture.
The code that uses FFI looks like the following:
(use gauche.ffi) (use gauche.native-type) (with-ffi (dlopen "/path/to/library") () ;; Define C functions and callbacks (define-c-function foo '(int c-string) 'int) ... ) ;; Call the defined C function (foo 4 "bar")
Foreign functions are defined within the form ‘with-ffi‘. Inside the form, you can define C functions and C callbacks. The defined C functions are visible from the rest of the code, and you can call it as a Scheme function.
• with-ffiフォーム: | ||
| • FFIサポート手続き: |
with-ffiフォーム ¶{gauche.ffi}
The dso form must be an expression that yields a dynamically
loaded object (dlopen, see FFIサポート手続き),
options is a keyword-value form to tune the behavior
of with-ffi, and form is a toplevel form
to define foreign interface (see below) which accesses the external
function provided by dso.
dso can be #f if form … only refer to
the values solely derived from the header files (you need to
specify :c-headers option in that case).
You can mix ordinary toplevel definitions like defin in
forms. However, with-ffi may reorder forms
depending on its kind.
This form does not create a scope; the toplevel definitions
of form … are spliced into the surrounding scope.
Some subsystem may need to insert the binding into the module’s
toplevel scope, so we recommend users to place with-ffi form
at the toplevel scope as well, to avoid the confusion.
:subsystem name:c-headers (header-name …){gauche.ffi}
{gauche.ffi}
{gauche.ffi}
{gauche.ffi}
{gauche.ffi}
This is a convenience procedure, and simply calls
dynamic-load with :init-function #f—that is,
telling the dynamic loader not to call Gauche-specific initialization function.
We find it worth to have this shortcut, because it aligns to the
programmer’s expectation.
Returns #<dlobj> object, which can be given to with-ffi
form.
The keyword arguments are passed to dynamic-load.
Paths specifies the list of directories to search dsoname
if it is given in a relative path—when omitted, the value of
the parameter dynamic-load-paths is used.
Versions specifies a list of version suffixes, each of
whose element may be an integer or a string. The version number is
attached after DSO suffix. See ダイナミックライブラリのロード, for
the details.
{gauche.ffi}
{gauche.ffi}
{gauche.ffi}
{gauche.ffi}