Talking to C
Because Recoil transpiles to C, calling C is direct and
declarative. A foreign block names the functions you want; a small
ABI layer (c-struct!, c-fn!, c-array!,
#extern) models exact C layouts when you need them.
foreign
Declare external C functions under a namespace. When the library tag is a
header tag like <stdlib.h>, Recoil emits the matching
#include automatically.
math: foreign <stdlib.h> [
abs: "abs" [i32! return: i32!]
]
x: math/abs -7
print x ; 7
c-string! at the boundary
c-string! is a boundary type for FFI declarations and approved
internals — use string! in ordinary code. Ownership metadata for
returns is written before the type:
env: foreign <stdlib.h> [
getenv: "getenv" [c-string! return: c-string!]
]
str: foreign <string.h> [
dup: "strdup" [c-string! return: [#owned c-string!]]
]
[#owned c-string!] is valid; [c-string! #owned] is
rejected.
Opaque pointers
Use :TypeName for opaque C pointers in FFI declarations.
curl: foreign <curl/curl.h> [
init: "curl_easy_init" [return: :CURL]
perform: "curl_easy_perform" [:CURL return: i32!]
cleanup: "curl_easy_cleanup" [:CURL]
]
ABI layouts
For exact C ABI modeling (distinct from ordinary struct!):
c-struct!
point!: make c-struct! [
x: i32!
y: i32!
]
c-fn! — callback fields
callbacks!: make c-struct! [
run: c-fn! [i32! return: i32!]
]
c-array! — fixed inline arrays
name-buffer!: make c-struct! [
buf: c-array! [char! 16]
]
c-array! is ABI-only and is not the same as vector!.
#extern & typed pointer reads
Declare imported ABI globals with #extern; read them through the
normal ABI-aware field/path rules.
#extern vector! __recoil_out_buf
Foreign code can return a raw c-pointer! that you reinterpret as
a typed ABI struct pointer for field reads:
raw: make c-pointer! foreign-func
header: as :event-header! raw ; /field access now resolves through the ABI shape
size-of & exports
Use size-of with ABI-visible types when allocating
foreign-visible storage:
bytes: make size! size-of c-pointer!
Recoil can export symbols for C consumers: functions via #export,
and globals where the ABI/codegen path supports it. See
Building libraries for using the generated
header from C.
The unsafe namespace
For direct access to common C standard-library functions without writing a
foreign block:
buf: unsafe/malloc 1024
unsafe/memset buf 0 1024
unsafe/free buf
Take the address of a binding with addr-of:
x: 42
p: addr-of x
Ports & I/O
Open handles — files, sockets, TLS, HTTP — are port! values that
follow an ownership model: borrow with a get-word to read/write, consume to
close.
fp: make port! file/open %data.txt
file/read :fp ; borrow
file/close fp ; consume
The layered networking model (tcp, tls,
http, https), server reactor, and the
ERR_PORT_* taxonomy have their own page — see
Ports.