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
}[package]
name = "croot"
version = "0.1.0"
unsafe = trueextern 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
"m"is C's math library and"c"the C library itself;"z"would be zlib (libz, orz.libon Windows).- A C call can do anything to memory, so it goes inside
unsafe { … }, and the package saysunsafe = true. cube_rootwraps the call: the rest of the program calls a safe Kavach function.
Types across the border
| Kavach | C |
|---|---|
Int, UInt64 | int64_t, uint64_t |
Int32, Int16, Int8, UInt32 … | the C integer of the same size |
Float | double |
Bool | bool |
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?