nandi/vflutter_ffipublic Fork 0
7fdf71219e3dd44c76c7be4120ff73a31d6237ce
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.

vflutter_ffi.dart · 88 lines · 2.6 KBDart Blame HistoryRaw
Initial commit: V -> Flutter FFI plugin ad0ccda nandi 13h ago1/// Idiomatic Dart surface over the V library.
2///
3/// Callers never see a Pointer, and never own V memory: every string that
4/// crosses the boundary is copied into Dart and the V allocation is released
5/// before the call returns.
6library vflutter_ffi;
7
8import 'dart:ffi';
9import 'dart:io';
10import 'dart:isolate';
11import 'package:ffi/ffi.dart';
12
13const String _libName = 'vflutter';
14
15DynamicLibrary _open() {
16 if (Platform.isMacOS || Platform.isIOS) {
17 // Static archive linked into the app binary.
18 return DynamicLibrary.process();
19 }
20 if (Platform.isAndroid || Platform.isLinux) {
21 return DynamicLibrary.open('lib$_libName.so');
22 }
23 if (Platform.isWindows) {
24 return DynamicLibrary.open('$_libName.dll');
25 }
26 throw UnsupportedError('vflutter_ffi: unsupported platform');
27}
28
29final DynamicLibrary _lib = _open();
30
31final void Function() _vfInit =
32 _lib.lookupFunction<Void Function(), void Function()>('vf_init');
33
34final int Function(int, int) _vfAdd =
35 _lib.lookupFunction<Int32 Function(Int32, Int32), int Function(int, int)>(
36 'vf_add');
37
38final Pointer<Utf8> Function(Pointer<Utf8>) _vfGreet = _lib.lookupFunction<
39 Pointer<Utf8> Function(Pointer<Utf8>),
40 Pointer<Utf8> Function(Pointer<Utf8>)>('vf_greet');
41
42final void Function(Pointer<Void>) _vfFree =
43 _lib.lookupFunction<Void Function(Pointer<Void>), void Function(Pointer<Void>)>(
44 'vf_free');
45
46bool _ready = false;
47
48/// Initialises the V runtime. Idempotent and cheap; called automatically by
49/// every API below, so you rarely need it directly.
50void ensureInitialized() {
51 if (_ready) return;
52 _vfInit();
53 _ready = true;
54}
55
56/// Adds two integers in V. The trivial case, useful as a liveness check.
57int add(int a, int b) {
58 ensureInitialized();
59 return _vfAdd(a, b);
60}
61
62/// Round-trips a string through V.
63///
64/// V allocates the result; this function copies it into a Dart [String] and
65/// frees the V allocation before returning, so there is nothing to release.
66String greet(String name) {
67 ensureInitialized();
68 final arg = name.toNativeUtf8();
69 Pointer<Utf8> res = nullptr;
70 try {
71 res = _vfGreet(arg);
72 if (res == nullptr) {
73 throw StateError('vf_greet returned null');
74 }
75 return res.toDartString();
76 } finally {
77 calloc.free(arg);
78 if (res != nullptr) _vfFree(res.cast());
79 }
80}
81
82/// Runs [greet] on a helper isolate.
83///
84/// V compiled with `-gc none` has no stop-the-world phase and no thread-local
85/// runtime state, so calls are safe from any isolate. Use this for work long
86/// enough to jank a frame.
87Future<String> greetAsync(String name) =>
88 Isolate.run(() => greet(name));