STklos Reference Manual

12. Foreign Function Interface

Contents
| *Top*
1 | Introduction
2 | Expressions
3 | Program structure
4 | Standard Procedures
5 | Regular Expressions
6 | Pattern Matching
7 | Exceptions and Conditions
8 | STklos Object System
9 | Threads, Mutexes and Condition Variables
10 | Customizations
11 | The ScmPkg Package System
12 | Foreign Function Interface
13 | Using the SLIB package
14 | SRFIs
15 | Index
| Bibliography

The STklos Foreign Function Interface (FFI for short) has been defined to allow an easy access to functions written in C without needing to build C-wrappers and, consequently, without any need to write C code. Note that the FFI is very machine dependent and that it works only on a limited set of architectures/systems 1. Moreover, since FFI allows very low level access, it is easy to crash the STklos VM when using an external C function.

Note that the support for FFI is still minimal and that it will evolve in future versions.

The definition of an external function is done with the define-external special form. This form takes as arguments a typed list of parameters and accepts several options to define the name of the function in the C world, the library which defines this function, ... The type of the function result and the type of its arguments are defined in Figure 2. This table lists the various keywords reserved for denoting types and their equivalence between the C and the Scheme worlds.

Name | Corresponding C type | Corresponding Scheme Type
--- | --- | ---
:void | void | none
:char | char | Scheme character
:short | short | Scheme integer
:ushort | unsigned short | Scheme integer
:int | int | Scheme integer
:uint | unsined int | Scheme integer
:long | long int | Scheme integer
:ulong | unsigned long int | Scheme integer
:float | float | Scheme real number
:double | double | Scheme real number
:boolean | int | boolean
:pointer | void * | Scheme pointer object or Scheme string
:string | char * | Scheme string
:obj | void * | Any Scheme object passed as is

Fig. 2: FFI types

`(define-external name parameters option)` | STklos syntax

The form `define-external` binds a new procedure to `name`. The arity of this new procedure is defined by the typed list of parameters given by `parameters`. This parameters list is a list of keywords (as defined in the previous table) or couples whose first element is the name of the parameter, and the second one is a type keyword. All the types defined in the above table, except `:void`, are allowed for the parameters of a foreign function.
`Define-external` accepts several options:

- `:return-type` is used to define the type of the value returned by the foreign function. The type returned must be chosen in the types specified in the table. For instance:

  >     (define-external maximum(:int :int)
  >        :return-type :int)

  defines the foreign function maximum which takes two C integers and returns an integer result. Omitting this option default to a result type equal to `:void` (i.e. the returned value is undefined).
- `:entry-name` is used to specify the name of the foreign function in the C world. If this option is omitted, the entry-name is supposed to be `name`. For instance:

  >     (define-external minimum((a :int) (b :int))
  >        :return-type :int
  >        :entry-name  "min")

  defines the Scheme function `minimum` whose application executes the C function called `min`.
- `:library-name` is used to specify the library which contains the foreign-function. If necessary, the library is loaded before calling the C function. So,

  >     (define-external minimum((a :int) (b :int))
  >        :return-type  :int
  >        :entry-name   "min"
  >         :library-name "libminmax")

  defines a function which will execute the function `min` located in the library `libminmax.xx` (where `xx` is the suffix used for shared libraries on the running system (generally `so`))

Hereafter, there are some commented definitions of external functions:

>      (define-external isatty ((fd :int))
>          :return-type :boolean)

>       (define-external system ((cmd :string))
>         :return-type :int)

>       (define-external ttyname (:int)
>         :return-type :string)

All these functions are defined in the C standard library, hence it is not necessary to specify the `:library-name` option.

- istty is declared here as a function which takes an integer and returns a boolean (in fact, the value returned by the C function isatty is an int, but we ask here to the FFI system to translate this result as a boolean value in the Scheme world).
- system is a function which takes a string as parameter and returns an int.
- ttyname is a function whih takes an int and returns a string. Note that in this function the name of the parameter has been omitted as within C prototypes.

If an external function receives an `:int` argument and is passed a Scheme bignum, which then doesn't fit a long int in C, the external function will signal an error. When a `:float` or `:double` argument is declared and is passed a Scheme real that requires so many bits so as to not be representable in that type, that argument will be silently taken as infinity.

>      (define-external c-abs ((fd :int))
>          :entry-name "abs"
>          :return-type :int)

>      (define-external c-fabs ((fd :double))
>          :entry-name "fabs"
>          :return-type :double)

>      (define-external c-fabsf ((fd :float))
>          :entry-name "fabsf"
>          :return-type :float)

>     (c-abs (- (expt 2 70)))    ⇒ Error
>     (c-fabs -1.0e+250)         ⇒ 1e+250
>     (c-fabsf -1.0e+250)        ⇒ +inf.0
>     (c-fabs (- (expt 10 300))) ⇒ 1e+300
>     (c-fabs (- (expt 10 600))) ⇒ +inf.0

TODO: describe malloc and malloc_atomic and their interaction with the GC

Note:
1: FFI system should works on the following architectures/systems: gcc_ppc_osx, gcc_sparc_unix, gcc_x64_unix, gcc_x86_unix.

This Html page has been produced by Skribe.
Last update Wed Nov 24 17:57:14 2021