Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Build a C library

Use export def to name the C symbol for a function. This calc.plenty module can also be imported and called by an ordinary Plenty program:

pub enum CalcError:
    Overflow

pub export def add(a: i32, b: i32) -> Result[i32, CalcError] = "calc_add":
    "Add two checked integers."
    result = checked:
        a + b
    result.map_error(def(error: OverflowError[i32]) -> CalcError: CalcError.Overflow)

pub export def increment(value: &mut i32) -> Result[(), CalcError] = "calc_increment":
    result = checked:
        *value + 1
    *value = result.map_error(def(error: OverflowError[i32]) -> CalcError: CalcError.Overflow)?
    Ok(())
import calc

def main() -> Result[(), IoError | calc.CalcError]:
    print(calc.add(20, 22)?)?
    mut value = 10i32
    calc.increment(&mut value)?
    print(value)?
    mut maximum = i32.MAX
    match calc.increment(&mut maximum):
        case Err(calc.CalcError.Overflow):
            print("overflow", maximum == i32.MAX)?
        case Ok(_):
            print("unexpected success")?
    Ok(())
42
11
overflow True

Arithmetic errors are mapped locally to a payload-free error enum supported by the C ABI. increment computes before assigning, so overflow leaves its borrowed value unchanged. Builtin OverflowError[T] carries a payload and cannot be exported directly. See exported error contracts.

pub makes the function accessible through source imports. export independently creates a C entry point in a library build. Libraries do not need main.

Save the module as calc.plenty, create a build directory, and run:

plenty --shared-library calc.plenty --library-name calc -o build/libcalc.so

The output includes calc.h, with a status-returning calc_add declaration and generated contract comments, and calc.plentyi, which Plenty consumers can import. Copy that generated interface into the consuming project’s source root and link libcalc.so using --link-arg; it replaces the source module there. C consumers include calc.h and link the library.

If you only have the binary, recover its Plenty interface without loading it:

plenty --extract-interface build/libcalc.so --library-name calc -o calc.plentyi
plenty --verify-interface build/libcalc.so calc.plentyi

For a static archive, use --static-library instead. Pass the native arguments listed in calc.link-args.txt after the archive when linking a C program.

For C callers, increment takes an int32_t * to an initialized value, borrowed exclusively for the call. Plenty callers get this borrowing contract from the generated interface.

Exports support numeric scalars, borrows, unit, supported Result values, and owned class handles. Read the generated header’s requirements even for simple APIs: runtime traps can terminate the process, and current libraries require serialized calls on one caller thread. See the library reference for supported export types and packaging details.