Guide
C libraries and bindgen
Extern blocks, the C types, @CLayout Structs, strings, callbacks, Unsafe, and fb bindgen.
A C library’s functions are declared in an Extern block in your code and called like your own
Functions. There are no .decls files and no wrapper to compile: fb links the library, and
fb bindgen writes the block from a header.
Extern
Extern "C" Lib "name" names one of the package’s [native] libraries; without Lib, the
symbols come from the C runtime and the system libraries every program links, as these do:
Import std.core
Extern "C"
Function abs(n: Int32): Int32
Function strlen(text: CString): UInt64
Function frexp(x: Float64, ByRef exponent: Int32): Float64
Function CAtoi(text: CString): Int32 = "atoi"
End Extern
Print(abs(-42), strlen("FutureBlitz"))
Local exponent: Int32 = 0
Local mantissa = frexp(48.0, ByRef exponent)
Print("48 is {mantissa} * 2^{exponent}")
Print(CAtoi("1234") + 1)42 11 48 is 0.75 * 2^6 1235
= "symbol"calls a C function by another name.- A
Stringpassed for aCStringparameter is copied with a NUL after it for the call alone. - A
ByRefparameter passes the variable’s address, so out-parameters need no Unsafe code. - An Extern Function is called from safe code; one whose misuse could break memory whatever it’s
given is declared
Unsafe Function, and onlyUnsafeblocks call it.
Types
| FutureBlitz | C |
|---|---|
Int8 to Int64, UInt8 to UInt64 | int8_t to uint64_t |
CLong, CULong, CWChar | long, unsigned long, wchar_t, the target’s sizes |
Float32, Float64 | float, double |
Bool | bool |
Ptr<T>, Ptr<Void> | T*, void* |
CString | const char* |
Callback(A, B): R | R (*)(A, B) |
@CLayout Struct | a struct, by value or through a Ptr |
A @CLayout Struct has its Fields where C puts them, so it passes by value as the target’s C ABI
does, as clang would.
Import std.core
@CLayout Struct DivResult
Field quot: Int32
Field rem: Int32
End Struct
Extern "C"
Function div(numerator: Int32, denominator: Int32): DivResult
End Extern
Local r = div(17, 5)
Print("17 / 5 is {r.quot} remainder {r.rem}")17 / 5 is 3 remainder 2
Callbacks
A Callback parameter takes a top-level Function whose types match, which C can call back.
Import std.core
Extern "C"
Function qsort(items: Ptr<Void>, count: UInt64, size: UInt64,
compare: Callback(Ptr<Void>, Ptr<Void>): Int32)
End Extern
Function Ascending(a: Ptr<Void>, b: Ptr<Void>): Int32
Unsafe
Local x = (a As Ptr<Int32>).Value
Local y = (b As Ptr<Int32>).Value
Return x < y ? -1 : (x > y ? 1 : 0)
End Unsafe
End Function
Local numbers: Int32[] = [42, 7, 19, 3]
Unsafe
qsort(AddressOf(numbers[0]), 4, 4, Ascending)
End Unsafe
Print(numbers)[3, 7, 19, 42]
Pointers are read and written only in Unsafe code, and the rest of the program stays checked.
fb bindgen
fb bindgen reads a C header with libclang and writes a module: a @CLayout Struct for each
struct, an Enum or Consts for each enum, a Const for each macro that’s a number, and one Public Extern "C" Lib block of its functions. What can’t map, like unions and varargs, is a // skipped:
comment saying why.
fb bindgen vecmath.h --lib vecmath -o vecmath.fbThen [native] in project.toml says where the library is, vecmath = { static = "libs/vecmath" }, and Import "./vecmath" uses it. A static library links into the executable,
so the program is still one file. The spec’s FFI chapter has every
rule, CData and Buffers too.
Report an issue with this page or with FutureBlitz on GitHub.