Skip to content
Kavachकवच

Calling C

Also known as: ffi foreign function interface c library native binding extern unsafe cgo pinvoke

● Advanced5 minBefore this: Unsafe

extern c declares the functions of a C library; Kavach calls them directly. Every call is unsafe, so you wrap it once in a safe function.

extern c "library" {
    fn c_name(param: CType) -> CType
}
syntax: Kavach code
[package]
name = "croot"
version = "0.1.0"
unsafe = true
kavach.toml: TOML code
extern c "m" {
    fn cbrt(x: Float) -> Float
}

extern c "c" {
    fn strlen(s: String) -> UInt64
}

fn cube_root(x: Float) -> Float {
    unsafe { cbrt(x) }
}

fn c_length(s: String) -> UInt64 {
    unsafe { strlen(s) }
}

fn main() {
    print(cube_root(27.0))
    print(c_length("namaste"))
}

The program ran and printed:

kavach run

3.07
src/main.kav: Kavach code, then what running it prints
  • "m" is C's math library and "c" the C library itself; "z" would be zlib (libz, or z.lib on Windows).
  • A C call can do anything to memory, so it goes inside unsafe { … }, and the package says unsafe = true.
  • cube_root wraps the call: the rest of the program calls a safe Kavach function.

Types across the border

KavachC
Int, UInt64int64_t, uint64_t
Int32, Int16, Int8, UInt32 …the C integer of the same size
Floatdouble
Boolbool
String (a parameter)const char*: a copy ending in a zero byte, valid during the call
Bytes (a parameter)const uint8_t*: a copy of the bytes, valid during the call; another argument says how many
Ptr<T>T*: a pointer, also to a struct
fn(…) -> … (a parameter)a function pointer, to a named Kavach function
no ->void

C functions run in native code: kavach build and kavach run --native. The interpreter stops at the first call of one and says to run the program natively.

One page for each form

Check yourself

QUIZ 1 / 1pick one
Why must a call to a C function be inside unsafe?