AtlatestRenderedmarkdown
Readme

sigil-ffi

Dynamic Foreign Function Interface for Sigil.

Call C library functions from Sigil at runtime without writing glue code. Built on a vendored dyncall, which provides portable calling conventions including struct-by-value passing on every supported arch (x86_64, aarch64, arm32, riscv, mips, ppc, sparc, s390, …).

Modules

ModulePurpose
(sigil ffi)Library load, symbol lookup, call, structs, callbacks

API summary

ProcedurePurpose
c-libraryOpen a shared library by name
c-library-closeClose a previously opened library
c-symbolResolve a symbol in a library
c-functionBind a function with arg-types and ret-type
define-c-libraryConvenience macro for binding many functions
c-sizeof / c-alignofQuery size/alignment of an FFI type
make-pointer / pointer-addressBuild/read raw pointer values
pointer-ref / pointer-set!Dereference a pointer at a typed offset
string->pointer / pointer->stringString/pointer round-trip
pointer->bytevector / bytevector->pointerBytevector bridge
c-alloc / c-free / with-c-allocManual memory
c-errno / c-strerrorerrno + strerror access
c-struct-layout / c-struct-ref / c-struct-set!Struct field access
c-struct->dict / dict->c-structStruct/dict marshalling
c-callback / c-callback-releaseBind a Scheme procedure as a C callback

FFI type constants: ffi/void, ffi/bool, ffi/int8..ffi/uint64, ffi/float, ffi/double, ffi/pointer, ffi/string, plus arch-relative ffi/int, ffi/uint, ffi/long, ffi/ulong, ffi/size-t.

System prerequisites

A working C toolchain. dyncall is vendored under vendor/dyncall/ and compiled in-tree; no system libdyncall required. Your platform must be one dyncall supports — see vendor/dyncall/dyncall/README* for the arch matrix.

Dependencies

  • sigil-stdlib

Build

sigil deps install
sigil build
sigil test --report

The first build compiles dyncall + dyncallback (vendor/dyncall/) plus native/ffi.c. Subsequent builds hit the cache.

Usage

(import (sigil ffi))

(define libm (c-library "libm"))
(define cbrt (c-function libm "cbrt" (list ffi/double) ffi/double))
(cbrt 27.0)                               ; => 3.0

(define libc (c-library "libc"))
(define getenv (c-function libc "getenv" (list ffi/string) ffi/string))
(getenv "HOME")                           ; => "/home/you"

define-c-library collapses the bind-many-functions pattern:

(import (sigil ffi))

(define-c-library libm "libm"
  (cbrt  (ffi/double) ffi/double)
  (sqrt  (ffi/double) ffi/double)
  (pow   (ffi/double ffi/double) ffi/double))

(cbrt 27.0)                               ; => 3.0
(pow 2.0 10.0)                            ; => 1024.0

License

BSD-3-Clause.

Vendored dyncall (under vendor/dyncall/) is distributed under a permissive ISC-style license — see vendor/dyncall/LICENSE. sigil-ffi's own sources are BSD-3-Clause.