This is a guide to calling C code from Scheme. See the FFI cookbook for a variety of examples.
This is about the simplest possible example. time(NULL)
is a
well-known way to get the current time in C. The time is returned as
the number of seconds elapsed since the epoch (on Unix, midnight,
January 1st, 1970).
From the REPL:
> (define libc (load-shared-object "libc.so")) ; libc.dylib on Mac > (define my-time (foreign-procedure "time" (uptr) unsigned-long)) > (my-time 0) 1581759013
Make sure to have the r7rs egg installed: chicken-install r7rs
Create a Scheme library mytime.sld
with an FFI stub in it:
(define-library (mytime)
(export mytime)
(import (scheme base) (chicken foreign))
(begin
(define mytime
(foreign-lambda* unsigned-long ()
"C_return(time(NULL));"))))
Compile the stub into a Unix object file (mytime.so
) with matching
import library (mytime.import.scm
): csc -X r7rs -R r7rs -sJ mytime.sld
Use it from the REPL:
$ csi #;1> (import (mytime)) #;2> (mytime) 1589710285
Create a Scheme library mytime.sld
with an FFI stub in it:
(define-library (mytime)
(export mytime)
(import (gambit))
(begin (define mytime
(c-lambda () unsigned-long
"___return(time(NULL));"))))
Compile the stub into a Unix object file (mytime.o1
): gsc mytime.sld
Use it from the REPL:
$ gsi . > (import (mytime)) > (mytime) 1581758667
Create the Scheme library file hello.sld
:
(define-library (hello)
(export hello)
(include-shared "hello"))
Create the FFI stub file hello.stub
:
(c-declare " static const char *my_hello(void) { return \"Hello world\"; } ") (define-c (const string) (hello "my_hello") ())
Generate a hello.c
file for the FFI stub: chibi-ffi hello.stub
Compile the stub into a Unix shared library (hello.so
or hello.dylib
):
$ export PKG_CONFIG_PATH="$HOME/.local/lib/pkgconfig" # May be needed $ chibi="$(pkg-config --libs --cflags chibi-scheme)" $ so=so # Linux, BSD; etc. $ so=dylib # Mac $ cc -Wall -fPIC -shared -o hello.$so hello.c $chibi
Use it from the REPL:
$ chibi-scheme > (import (hello)) > (hello) "Hello world"
Make sure to have the r7rs egg installed: chicken-install r7rs
Create a Scheme library hello.sld
with an FFI stub in it:
(define-library (hello)
(export hello)
(import (scheme base) (chicken foreign))
(begin (define hello
(foreign-lambda* c-string ()
"C_return(\"Hello world\");"))))
Compile the stub into a Unix object file (hello.so
) with matching
import library (hello.import.scm
): csc -X r7rs -R r7rs -sJ hello.sld
Use it from the REPL:
$ csi #;1> (import (hello)) #;2> (hello) "Hello world"
Create a Scheme library hello.sld
with an FFI stub in it:
(define-library (hello)
(export hello)
(import (gambit))
(begin (define hello
(c-lambda () nonnull-char-string
"___return(\"Hello world\");"))))
Compile and link it into a Unix shared library: gsc hello.sld
Use it from the REPL:
$ gsi . > (import (hello)) > (hello) "Hello world"