Foreign Function Interface
35.1 Calling C Functions
C types: cint, cuint, clong, cshort, cchar, cfloat, cdouble, csize_t, cstring, pointer, ptr T, UncheckedArray[T].
proc printf(fmt: cstring): cint {.importc, varargs, header: "<stdio.h>", discardable.}
printf("Hello %s, %d\n", "C", 42)
proc strlen(s: cstring): csize_t {.importc, header: "<string.h>".}
proc c_sqrt(x: cdouble): cdouble {.importc: "sqrt", header: "<math.h>".}35.2 Importing C Structs, Enums, and Constants
type
CTimeval {.importc: "struct timeval", header: "<sys/time.h>".} = object
tv_sec: clong
tv_usec: clong
var EOF_C {.importc: "EOF", header: "<stdio.h>".}: cint
type Color {.size: sizeof(cint).} = enum cRed, cGreen35.3 Dynamic Libraries
const libName = when defined(windows): "mylib.dll" elif defined(macosx): "libmylib.dylib" else: "libmylib.so"
proc add(a, b: cint): cint {.importc, dynlib: libName, cdecl.}
import std/dynlib # manual loading
let lib = loadLib("libm.so.6")
let cos = cast[proc (x: cdouble): cdouble {.cdecl, gcsafe.}](lib.symAddr("cos"))35.4 Compiling C Sources Along with Nim
{.compile: "vendor/fast.c".}
{.passC: "-I./vendor -O3".}
{.passL: "-lm -lz".}
proc fastSum(a: ptr cint, n: cint): cint {.importc.}
{.emit: """
static int helper(int x) { return x * 2; }
""".}
proc helper(x: cint): cint {.importc, nodecl.}35.5 Exporting Nim to C (Building Libraries)
Call NimMain() from the C side to initialize the Nim runtime (globals).
# mylib.nim
proc nimAdd(a, b: cint): cint {.exportc, dynlib, cdecl.} = a + bnim c --app:lib --noMain -d:release mylib.nim # shared library (.so/.dll/.dylib)
nim c --app:staticlib --noMain mylib.nim # static library
nim c --header --noMain mylib.nim # generate a C header35.6 C++ Interop
Patterns: # = first argument, @ = remaining arguments, '0 = return type, '*1 = the type's generic parameter.
type StdVector[T] {.importcpp: "std::vector", header: "<vector>".} = object
proc newVector[T](): StdVector[T] {.importcpp: "std::vector<'*0>()", constructor.}
proc push_back[T](v: var StdVector[T], x: T) {.importcpp: "#.push_back(@)".}
proc size[T](v: StdVector[T]): csize_t {.importcpp: "size".}
var v = newVector[cint]()
v.push_back(1)
echo v.sizenim cpp -r app.nim35.7 Wrapper Generators
c2nim (translate C headers to Nim), futhark (automatic C header import via libclang), nimterop, opir.
Python: nimpy (call Python and build Python modules), nimporter. Also JNI wrappers (jnim), Rust via the C ABI, Lua (nimLUA).