module main // --------------------------------------------------------------------------- // C-ABI surface consumed by Dart FFI. // // Rules for everything below: // * only C-compatible types cross the boundary (int, f64, &char, voidptr) // * V strings/arrays/options/sumtypes never cross; convert first // * anything V allocates and hands out is released by vf_free // --------------------------------------------------------------------------- // Touches the V runtime so the GC and global initialisers are demonstrably // live. The ELF/Mach-O constructor emitted by `v -shared` already does this; // this exists for static-archive builds (iOS) where the caller wants a // guaranteed, idempotent entry point. @[export: 'vf_init'] fn vf_init() { probe := 'vf' _ = probe.len } @[export: 'vf_add'] fn vf_add(a int, b int) int { return a + b } // Returns a V-allocated C string. Caller releases it with vf_free. // // Built with `-gc none`, so every intermediate V allocation here must be // freed by hand. Only the returned buffer outlives the call. @[export: 'vf_greet'] fn vf_greet(name &char) &char { n := unsafe { cstring_to_vstring(name) } res := 'Hello, ${n}, from V!' out := unsafe { res.str } unsafe { n.free() } return out } @[export: 'vf_free'] fn vf_free(p voidptr) { unsafe { free(p) } }