nandi/vflutter_ffipublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/vflutter_ffi.git
git clone ssh://git@rickub.com/nandi/vflutter_ffi.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

README.md · 144 lines · 5.6 KBmarkdown Blame HistoryRaw
Initial commit: V -> Flutter FFI plugin ad0ccda nandi 4h ago1# vflutter_ffi
2
3Write application logic in **V**, call it from **Flutter** over `dart:ffi`.
4
5Built on Flutter's `plugin_ffi` template. No platform channels, no method-channel
6serialisation — Dart calls V through the C ABI directly.
7
8## How it works
9
10V compiles to C. That is the whole trick:
11
12```
13src/vflutter.v --[ v -shared -gc none ]--> C --[ NDK / clang / MSVC ]--> libvflutter.so
14```
15
16V never cross-compiles for the target. It only emits C, and the platform's own
17toolchain owns the ABI, sysroot and flags. That is why Android arm64, iOS
18arm64, Linux, macOS and Windows all work from one source file.
19
20| Platform | Built by | Artifact |
21|---|---|---|
22| Android | NDK via `android/build.gradle``src/CMakeLists.txt` | `libvflutter.so` per ABI |
23| Linux / Windows | Flutter's CMake → `src/CMakeLists.txt` | shared library, auto-bundled |
24| iOS / macOS | CocoaPods compiles pre-generated C | static archive in the app binary |
25
26iOS is the odd one out: Xcode's build sandbox can't run `v`, and App Store
27builds want a static archive. So `tool/gen_ios_sources.sh` generates the C ahead
28of time into `ios/Classes/`, and that is checked in. **Re-run it whenever
29`src/vflutter.v` changes.**
30
31## The two rules
32
33Everything that goes wrong with this bridge goes wrong in one of two ways.
34
35**1. Only C types cross the boundary.**
36`int`, `f64`, `&char`, `voidptr`. Never a V string, array, map, option or
37sumtype — those have V-specific layouts Dart cannot read. Convert at the edge.
38
39**2. The library is built `-gc none`, so V code must free its own temporaries.**
40
41This is the one that bites. Boehm GC can't be cross-compiled per-ABI without
42pain, and a C-ABI library with explicit ownership doesn't need it — but it means
43*every* intermediate allocation inside an exported function leaks unless freed:
44
45```v
46@[export: 'vf_greet']
47fn vf_greet(name &char) &char {
48 n := unsafe { cstring_to_vstring(name) } // allocates
49 res := 'Hello, ${n}, from V!' // allocates
50 out := unsafe { res.str } // handed to the caller
51 unsafe { n.free() } // <-- without this, ~40 bytes/call
52 return out
53}
54```
55
56Measured on this repo: omitting `n.free()` leaks ~12 MB per 300k calls. With it,
57RSS is flat at 300k and 900k calls.
58
59Ownership across the boundary: **V allocates, Dart copies, V frees.** The Dart
60wrapper in `lib/vflutter_ffi.dart` does the `vf_free` in a `finally`, so callers
61never hold a pointer and never leak.
62
Add a justfile f7c3825 nandithebull 4m ago63## Quick start
64
65With [`just`](https://github.com/casey/just):
66
67```
68just mandelbrot # build the V library and run the fractal explorer
69just test # analyze + the example's test suite
70just bench # V vs Dart timings for the same frame
71just --list # everything else
72```
73
74Flutter is expected at `~/flutter/bin`; set `FLUTTER_BIN` if yours lives
75elsewhere.
76
Initial commit: V -> Flutter FFI plugin ad0ccda nandi 4h ago77## Usage
78
79```dart
80import 'package:vflutter_ffi/vflutter_ffi.dart' as v;
81
82v.add(20, 22); // 42
83v.greet('Flutter'); // "Hello, Flutter, from V!"
84await v.greetAsync('isolate'); // same, off the UI isolate
85```
86
87`-gc none` means no stop-the-world phase and no thread-local runtime state, so
88calls are safe from any isolate. Use `Isolate.run` for anything long enough to
89jank a frame.
90
Add a Mandelbrot example app, and a V kernel worth demonstrating 81540bb nandithebull 12m ago91For bulk data, let Dart own the buffer and have V fill it in place — then
92nothing crosses the boundary that needs freeing, and independent slices can be
93computed concurrently:
94
95```dart
96final view = v.FractalView(width: 800, height: 600, maxIter: 500);
97final pixels = await v.renderParallel(view, tiles: 4); // RGBA8888
98```
99
100## Is V faster than Dart?
101
102For the numeric kernel in the example: **no, not meaningfully.** Measured at
103800x600 / 500 iterations on an 8-core Linux box, V through C takes ~152 ms
104against Dart AOT's ~165 ms — inside the noise of a ~10% margin. Dart's AOT
105compiler is good at scalar floating-point loops.
106
107What the bridge does buy you is the ability to *write the logic in V* — or
108reuse V you already have — with a C ABI that is cheap to call and safe to call
109concurrently. Pick it for the language, not for an expected speedup. And build
110with optimisation on: at `-O0` the same kernel is roughly 2x slower than Dart,
111which is what `tool/build.sh` and `src/CMakeLists.txt` now guard against.
112
Initial commit: V -> Flutter FFI plugin ad0ccda nandi 4h ago113## Adding a function
114
1151. Export it in `src/vflutter.v` with `@[export: 'vf_yourthing']`, freeing temporaries.
1162. Declare it in `src/vflutter.h`.
1173. Wrap it in `lib/vflutter_ffi.dart`.
1184. `./tool/gen_ios_sources.sh` to refresh the iOS C.
1195. `./tool/build.sh` to smoke-test the host build.
120
121Step 2 also feeds `dart run ffigen --config ffigen.yaml` if you'd rather
122generate the raw bindings than hand-write them.
123
124## Status
125
Add a Mandelbrot example app, and a V kernel worth demonstrating 81540bb nandithebull 12m ago126Verified on Linux with V 0.5.2, Dart 3 and Flutter 3.47: host build, string
127round-trip, isolate dispatch, 900k-call memory stability, and the example app
128built and run as a release Linux binary (CMake -> `v` -> NDK/clang path
129included). The Android/iOS/Windows glue is written to the standard `plugin_ffi`
130contract but is not exercised here — it needs the respective toolchains.
Initial commit: V -> Flutter FFI plugin ad0ccda nandi 4h ago131
132## Layout
133
134```
135src/vflutter.v the V source — the only file you normally edit
136src/vflutter.h C declarations (ffigen input, Xcode input)
137src/CMakeLists.txt V -> C -> shared lib; shared by Android/Linux/Windows
138lib/vflutter_ffi.dart the Dart API callers use
139ios/, macos/ pre-generated C + podspec (static archive)
140android/build.gradle NDK build via externalNativeBuild
141tool/build.sh host build + export smoke test
142tool/gen_ios_sources.sh regenerate ios/ and macos/ C after editing the V source
Add a Mandelbrot example app, and a V kernel worth demonstrating 81540bb nandithebull 12m ago143example/ Flutter app exercising the bridge (see example/README.md)
Initial commit: V -> Flutter FFI plugin ad0ccda nandi 4h ago144```