For Development HEAD DRAFTSearch (procedure/syntax/module):

9.12 gauche.ffi - FFI

Module: gauche.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:

:native

A 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.

:stub

A 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.

:aot

A 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.


9.12.1 with-ffiフォーム

Macro: with-ffi dso options form …

{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 …)
Macro: define-c-function name arg-types return-type

{gauche.ffi}

Macro: define-c-callback name ((var type) …) return-type body …

{gauche.ffi}

Macro: define-c-constant name :optional type

{gauche.ffi}

Macro: define-c-enum name (enumerator …) :optional base-type
Macro: define-c-enum (name tag) (enumerator …) :optional base-type

{gauche.ffi}


9.12.2 FFIサポート手続き

Function: dlopen dsoname :key paths versions

{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.

Function: default-ffi-subsystem

{gauche.ffi}

Function: ffi-subsystem-available? name

{gauche.ffi}

Function: native-alloc size-or-type

{gauche.ffi}

Function: native-free handle

{gauche.ffi}



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT