{{~ Aditionally delete this line and fill out the template below ~}}
This library follows the Hyperpolymath RSR Standard for ABI and FFI design:
- ABI (Application Binary Interface) defined in Idris2 with formal proofs
- FFI (Foreign Function Interface) implemented in Zig for C compatibility
- Generated C headers bridge Idris2 ABI to Zig FFI
- Any language can call through standard C ABI
βββββββββββββββββββββββββββββββββββββββββββββββ
β ABI Definitions (Idris2) β
β src/abi/ β
β - Types.idr (Type definitions) β
β - Layout.idr (Memory layout proofs) β
β - Foreign.idr (FFI declarations) β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
β generates (at compile time)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β C Headers (auto-generated) β
β generated/abi/{{project}}.h β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
β imported by
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β FFI Implementation (Zig) β
β ffi/zig/src/main.zig β
β - Implements C-compatible functions β
β - Zero-cost abstractions β
β - Memory-safe by default β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
β compiled to lib{{project}}.so/.a
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β Any Language via C ABI β
β - Rust, ReScript, Julia, Python, etc. β
βββββββββββββββββββββββββββββββββββββββββββββββ
{{project}}/
βββ src/
β βββ abi/ # ABI definitions (Idris2)
β β βββ Types.idr # Core type definitions with proofs
β β βββ Layout.idr # Memory layout verification
β β βββ Foreign.idr # FFI function declarations
β βββ lib/ # Core library (any language)
β
βββ ffi/
β βββ zig/ # FFI implementation (Zig)
β βββ build.zig # Build configuration
β βββ build.zig.zon # Dependencies
β βββ src/
β β βββ main.zig # C-compatible FFI implementation
β βββ test/
β β βββ integration_test.zig
β βββ include/
β βββ {{project}}.h # C header (optional, can be generated)
β
βββ generated/ # Auto-generated files
β βββ abi/
β βββ {{project}}.h # Generated from Idris2 ABI
β
βββ bindings/ # Language-specific wrappers (optional)
βββ rust/
βββ rescript/
βββ julia/
Idris2's dependent types allow proving properties about the ABI at compile-time:
-- Prove struct size is correct
public export
exampleStructSize : HasSize ExampleStruct 16
-- Prove field alignment is correct
public export
fieldAligned : Divides 8 (offsetOf ExampleStruct.field)
-- Prove ABI is platform-compatible
public export
abiCompatible : Compatible (ABI 1) (ABI 2)Encode invariants that C/Zig cannot express:
-- Non-null pointer guaranteed at type level
data Handle : Type where
MkHandle : (ptr : Bits64) -> {auto 0 nonNull : So (ptr /= 0)} -> Handle
-- Array with length proof
data Buffer : (n : Nat) -> Type where
MkBuffer : Vect n Byte -> Buffer nPlatform-specific types with compile-time selection:
CInt : Platform -> Type
CInt Linux = Bits32
CInt Windows = Bits32
CSize : Platform -> Type
CSize Linux = Bits64
CSize Windows = Bits64Prove that new ABI versions are backward-compatible:
-- Compiler enforces compatibility
abiUpgrade : ABI 1 -> ABI 2
abiUpgrade old = MkABI2 {
-- Must preserve all v1 fields
v1_compat = old,
-- Can add new fields
new_features = defaults
}Zig exports C-compatible functions naturally:
export fn library_function(param: i32) i32 {
return param * 2;
}Compile-time safety without runtime overhead:
// Null check enforced at compile time
const handle = init() orelse return error.InitFailed;
defer free(handle);Built-in cross-compilation to any platform:
zig build -Dtarget=x86_64-linux
zig build -Dtarget=aarch64-macos
zig build -Dtarget=x86_64-windowsNo runtime, no libc required (unless explicitly needed):
// Minimal binary size
pub const lib = @import("std");
// Only includes what you usecd ffi/zig
zig build # Build debug
zig build -Doptimize=ReleaseFast # Build optimized
zig build test # Run testscd src/abi
idris2 --cg c-header Types.idr -o ../../generated/abi/{{project}}.hcd ffi/zig
# Linux x86_64
zig build -Dtarget=x86_64-linux
# macOS ARM64
zig build -Dtarget=aarch64-macos
# Windows x86_64
zig build -Dtarget=x86_64-windows#include "{{project}}.h"
int main() {
void* handle = {{project}}_init();
if (!handle) return 1;
int result = {{project}}_process(handle, 42);
if (result != 0) {
const char* err = {{project}}_last_error();
fprintf(stderr, "Error: %s\n", err);
}
{{project}}_free(handle);
return 0;
}Compile with:
gcc -o example example.c -l{{project}} -L./zig-out/libimport {{PROJECT}}.ABI.Foreign
main : IO ()
main = do
Just handle <- init
| Nothing => putStrLn "Failed to initialize"
Right result <- process handle 42
| Left err => putStrLn $ "Error: " ++ errorDescription err
free handle
putStrLn "Success"#[link(name = "{{project}}")]
extern "C" {
fn {{project}}_init() -> *mut std::ffi::c_void;
fn {{project}}_free(handle: *mut std::ffi::c_void);
fn {{project}}_process(handle: *mut std::ffi::c_void, input: u32) -> i32;
}
fn main() {
unsafe {
let handle = {{project}}_init();
assert!(!handle.is_null());
let result = {{project}}_process(handle, 42);
assert_eq!(result, 0);
{{project}}_free(handle);
}
}const lib{{project}} = "lib{{project}}"
function init()
handle = ccall((:{{project}}_init, lib{{project}}), Ptr{Cvoid}, ())
handle == C_NULL && error("Failed to initialize")
handle
end
function process(handle, input)
result = ccall((:{{project}}_process, lib{{project}}), Cint, (Ptr{Cvoid}, UInt32), handle, input)
result
end
function cleanup(handle)
ccall((:{{project}}_free, lib{{project}}), Cvoid, (Ptr{Cvoid},), handle)
end
# Usage
handle = init()
try
result = process(handle, 42)
println("Result: $result")
finally
cleanup(handle)
endcd ffi/zig
zig build testcd ffi/zig
zig build test-integration-- Compile-time verification
%runElab verifyABI
-- Runtime checks
main : IO ()
main = do
verifyLayoutsCorrect
verifyAlignmentsCorrect
putStrLn "ABI verification passed"When modifying the ABI/FFI:
-
Update ABI first (
src/abi/*.idr)- Modify type definitions
- Update proofs
- Ensure backward compatibility
-
Generate C header
idris2 --cg c-header src/abi/Types.idr -o generated/abi/{{project}}.h -
Update FFI implementation (
ffi/zig/src/main.zig)- Implement new functions
- Match ABI types exactly
-
Add tests
- Unit tests in Zig
- Integration tests
- ABI verification tests
-
Update documentation
- Function signatures
- Usage examples
- Migration guide (if breaking changes)
PMPL-1.0-or-later