C Interoperability

26.1 Calling C Functions

C declarations use the C. prefix. #include, #flag (compiler/linker flags), and #pkgconfig integrate the build.

#include <stdio.h>
#include <math.h>
#flag -lm

fn C.printf(fmt &char, ...) int
fn C.sqrt(x f64) f64
fn C.strlen(s &char) usize

fn main() {
	C.printf(c'Hello from C: %d\n', 42)
	println(C.sqrt(16.0))
	s := 'hello'
	println(C.strlen(&char(s.str)))
}

26.2 Flags and Platform-Specific Linking

#flag -I @VMODROOT/c/include
#flag -L @VMODROOT/c/lib
#flag linux -lsqlite3
#flag windows -luser32
#flag darwin -framework Cocoa
#pkgconfig gtk+-3.0
#flag @VMODROOT/c/helper.o
#include "@VMODROOT/c/helper.h"

26.3 C Structs, Enums, and Types

#include <time.h>
@[typedef]
struct C.tm {
	tm_year int
	tm_mon  int
	tm_mday int
}
fn C.time(t &i64) i64
fn C.localtime(t &i64) &C.tm

fn main() {
	mut t := i64(0)
	C.time(&t)
	tm := C.localtime(&t)
	println('${tm.tm_year + 1900}-${tm.tm_mon + 1}-${tm.tm_mday}')
}

26.4 Strings and Memory Across the Boundary

v_str := 'hello'
c_ptr := &char(v_str.str)              // V string → C string (null-terminated)
back := unsafe { cstring_to_vstring(c_ptr) }   // C → V (copies)
back2 := unsafe { tos_clone(&u8(c_ptr)) }
// C callbacks
fn my_cb(x int) int { return x * 2 }
fn C.register_callback(cb fn (int) int)
C.register_callback(my_cb)

26.5 Compiling C Sources and Exporting V to C

#flag @VMODROOT/c/fast.c                 // compile a C source file along with the program
@[export: 'v_add']
pub fn add(a int, b int) int { return a + b }
v -shared -o libmylib.so mylib.v       # build a shared library
v -o mylib.c mylib.v                   # emit C source only

26.6 Wrapping C Libraries

Write a thin module with C. declarations plus an idiomatic V API (results, structs, free() methods).

Examples in vlib: db.sqlite, db.pg, db.mysql, sokol, stbi, net.openssl, clipboard.

c2v (Module 44) can generate bindings automatically: v translate wrapper header.h.