Lyricdev
GitHub

std.ffi

Provides the types that cross into a C function and back.

A C function is declared with extern "C" and called as any other: its integers, floats and bool cross as they are, a @Layout(C) struct crosses by value, and the types here stand for what C holds by address. Ptr is a pointer to memory C manages, ?Ptr one that may be null; CStr is C's text, const char *. A string handed to a CStr parameter crosses without a copy, its bytes as they lie, for the time of the call.

Reading and writing through a pointer, moving it and changing what it points at, and C's own memory — alloc and free — stand in an unsafe { … } block: there the program says it holds to what the compiler cannot see, that the memory is there and of the type. Calling a C function is not unsafe, and neither is Ptr of an array or a slice's elements.

Examples

import std.ffi { CStr };
import std.io { println };

extern "C" fn strlen(s: CStr): uint;

fn main(): void {
    println(strlen("hello"));
}
5

Types

Ptr struct — A pointer to a T in memory C manages, never null: T * where a C function takes or returns one.
Callback class — A Lyric closure C calls, with its state: C's void *userdata beside a function pointer.
GcHandle class — An object of a class held for C: the collector keeps it while the handle does, and GcHandle.asPtr is the void * C keeps and hands back — the userdata of a C API that holds a Lyric object across its calls.
CEnum interface — An enum C holds as its integer: CEnum.from reads the integer C left in a struct's field or handed over as a plain integer, and CEnum.value gives the integer back.
Library class — A shared library loaded while the program runs — a .so, .dylib or .dll — and the C functions in it, found by their names.
CStr struct — A C string: the address of bytes a NUL ends, const char * at a C function's boundary.

Functions

pub fn stash(e: Error): void

Keeps e for the code around the C call that called this function: a function C calls throws nothing, since C would not know what to do with it, and this is how its error crosses. The code that called C takes it with takeStashed when C returns.

One error waits at a time, the running task's: a second, before the first is taken, is dropped — the first went wrong first.

pub fn takeStashed(): ?Error

Returns the error a function C called kept with stash, and forgets it; null where none waits.

pub fn alloc<T>(count: int): Ptr<T>

Returns count values of T from C's heap, each set to zero — what C's calloc gives, to be given back with free. Unsafe: nothing frees it but the program.

Panics

Where count is negative, and where C's heap has no memory left.

pub fn free<T>(p: Ptr<T>): void

Gives the memory alloc gave back to C's heap. Unsafe: nothing reads it afterwards but the program's word says so.

Extensions

extend<T> T[]
pub fn asPtr(): Ptr<T>

Returns a pointer to the first element: the elements lie one after the other, as C's array does. It holds the array no longer than the array is otherwise held, and it is no pointer to anything where the array is empty.

A C function that keeps the pointer past its return needs the array held as long: by a field of an object a GcHandle pins, until C is done with it. The collector moves nothing, so the pointer stays good while the array lives.

extend<T> Slice<T>
pub fn asPtr(): Ptr<T>

Returns a pointer to the slice's first element, in the memory of its array. It holds the array no longer than the array is otherwise held, and it is no pointer to anything where the slice is empty. A pointer C keeps past its call needs the array held as long, as an array's asPtr says.