nandi/vflutter_ffipublic Fork 0
ad0ccdab6e9bda61631966b5d85747e3e6d533db
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 · 106 lines · 4.0 KBmarkdown Blame HistoryRaw
Initial commit: V -> Flutter FFI plugin ad0ccda nandi 6h 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
63## Usage
64
65```dart
66import 'package:vflutter_ffi/vflutter_ffi.dart' as v;
67
68v.add(20, 22); // 42
69v.greet('Flutter'); // "Hello, Flutter, from V!"
70await v.greetAsync('isolate'); // same, off the UI isolate
71```
72
73`-gc none` means no stop-the-world phase and no thread-local runtime state, so
74calls are safe from any isolate. Use `Isolate.run` for anything long enough to
75jank a frame.
76
77## Adding a function
78
791. Export it in `src/vflutter.v` with `@[export: 'vf_yourthing']`, freeing temporaries.
802. Declare it in `src/vflutter.h`.
813. Wrap it in `lib/vflutter_ffi.dart`.
824. `./tool/gen_ios_sources.sh` to refresh the iOS C.
835. `./tool/build.sh` to smoke-test the host build.
84
85Step 2 also feeds `dart run ffigen --config ffigen.yaml` if you'd rather
86generate the raw bindings than hand-write them.
87
88## Status
89
90Verified on Linux with V 0.5.2 + Dart 3: build, string round-trip, isolate
91dispatch, and 900k-call memory stability. The Android/iOS/Windows glue is
92written to the standard `plugin_ffi` contract but is not exercised here —
93it needs a Flutter SDK and the respective toolchains.
94
95## Layout
96
97```
98src/vflutter.v the V source — the only file you normally edit
99src/vflutter.h C declarations (ffigen input, Xcode input)
100src/CMakeLists.txt V -> C -> shared lib; shared by Android/Linux/Windows
101lib/vflutter_ffi.dart the Dart API callers use
102ios/, macos/ pre-generated C + podspec (static archive)
103android/build.gradle NDK build via externalNativeBuild
104tool/build.sh host build + export smoke test
105tool/gen_ios_sources.sh regenerate ios/ and macos/ C after editing the V source
106```