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.

backend_native.dart · 144 lines · 4.3 KBDart Blame HistoryRaw
Replace V with Nim 472eb49 nandithebull 8h ago1/// Native backend: the Nim library as a shared object / static archive, reached
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago2/// through `dart:ffi`.
3///
Replace V with Nim 472eb49 nandithebull 8h ago4/// Selected by the conditional import in `../nimflutter_ffi.dart` on every
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago5/// target except web. The web twin is `backend_web.dart`; the two files must
6/// keep the same top-level signatures.
7library;
8
9import 'dart:ffi';
10import 'dart:io';
11import 'dart:isolate';
12import 'dart:typed_data';
13
14import 'package:ffi/ffi.dart';
15
16import 'fractal_view.dart';
17
18const String backendName = 'dart:ffi';
19
20/// Isolates are real threads here, and `-gc none` means there is no
21/// stop-the-world phase to serialise them.
22const bool supportsIsolateParallelism = true;
23
Render in parallel on web, via a pool of Web Workers 4506a58 nandithebull 7h ago24/// What one unit of parallelism is called here. Purely for display.
25const String parallelUnitName = 'isolate';
26
Replace V with Nim 472eb49 nandithebull 8h ago27const String _libName = 'nimflutter';
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago28
29DynamicLibrary _open() {
30 if (Platform.isMacOS || Platform.isIOS) {
31 // Static archive linked into the app binary.
32 return DynamicLibrary.process();
33 }
34 if (Platform.isAndroid || Platform.isLinux) {
35 return DynamicLibrary.open('lib$_libName.so');
36 }
37 if (Platform.isWindows) {
38 return DynamicLibrary.open('$_libName.dll');
39 }
Replace V with Nim 472eb49 nandithebull 8h ago40 throw UnsupportedError('nimflutter_ffi: unsupported platform');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago41}
42
43final DynamicLibrary _lib = _open();
44
Replace V with Nim 472eb49 nandithebull 8h ago45final void Function() _nfInit =
46 _lib.lookupFunction<Void Function(), void Function()>('nf_init');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago47
Replace V with Nim 472eb49 nandithebull 8h ago48final int Function(int, int) _nfAdd =
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago49 _lib.lookupFunction<Int32 Function(Int32, Int32), int Function(int, int)>(
Replace V with Nim 472eb49 nandithebull 8h ago50 'nf_add');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago51
Replace V with Nim 472eb49 nandithebull 8h ago52final Pointer<Utf8> Function(Pointer<Utf8>) _nfGreet = _lib.lookupFunction<
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago53 Pointer<Utf8> Function(Pointer<Utf8>),
Replace V with Nim 472eb49 nandithebull 8h ago54 Pointer<Utf8> Function(Pointer<Utf8>)>('nf_greet');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago55
Replace V with Nim 472eb49 nandithebull 8h ago56final void Function(Pointer<Void>) _nfFree = _lib.lookupFunction<
57 Void Function(Pointer<Void>), void Function(Pointer<Void>)>('nf_free');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago58
59final void Function(Pointer<Uint8>, int, int, int, double, double, double, int,
Replace V with Nim 472eb49 nandithebull 8h ago60 int, int) _nfMandelbrot = _lib.lookupFunction<
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago61 Void Function(Pointer<Uint8>, Size, Int32, Int32, Double, Double,
62 Double, Int32, Int32, Int32),
63 void Function(Pointer<Uint8>, int, int, int, double, double, double,
Replace V with Nim 472eb49 nandithebull 8h ago64 int, int, int)>('nf_mandelbrot');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago65
66bool _ready = false;
67
68bool get isInitialized => _ready;
69
70/// Loading a shared object is synchronous, so this is only here to match the
71/// web backend's contract. Nothing awaits anything.
72Future<void> initialize() async => ensureInitialized();
73
74void ensureInitialized() {
75 if (_ready) return;
Replace V with Nim 472eb49 nandithebull 8h ago76 _nfInit();
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago77 _ready = true;
78}
79
80int add(int a, int b) {
81 ensureInitialized();
Replace V with Nim 472eb49 nandithebull 8h ago82 return _nfAdd(a, b);
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago83}
84
85String greet(String name) {
86 ensureInitialized();
87 final arg = name.toNativeUtf8();
88 Pointer<Utf8> res = nullptr;
89 try {
Replace V with Nim 472eb49 nandithebull 8h ago90 res = _nfGreet(arg);
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago91 if (res == nullptr) {
Replace V with Nim 472eb49 nandithebull 8h ago92 throw StateError('nf_greet returned null');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago93 }
94 return res.toDartString();
95 } finally {
96 calloc.free(arg);
Replace V with Nim 472eb49 nandithebull 8h ago97 if (res != nullptr) _nfFree(res.cast());
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago98 }
99}
100
101Future<String> greetAsync(String name) => Isolate.run(() => greet(name));
102
103Uint8List renderBand(FractalView view, int y0, int y1) {
104 ensureInitialized();
105 final rows = y1 - y0;
106 if (rows <= 0) return Uint8List(0);
107
108 final bytes = rows * view.width * 4;
109 final buf = calloc<Uint8>(bytes);
110 try {
Replace V with Nim 472eb49 nandithebull 8h ago111 // `bytes` is the real allocation size, not a restatement of the band: Nim
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago112 // checks it before writing, so an arithmetic slip here is caught there
113 // rather than becoming a heap overflow.
Replace V with Nim 472eb49 nandithebull 8h ago114 _nfMandelbrot(buf, bytes, view.width, view.height, view.centerX,
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago115 view.centerY, view.scale, view.maxIter, y0, y1);
116 // Copy out of native memory before it is freed.
117 return Uint8List.fromList(buf.asTypedList(bytes));
118 } finally {
119 calloc.free(buf);
120 }
121}
122
123Future<Uint8List> renderParallel(FractalView view, int tiles) async {
124 ensureInitialized();
125 final count = tiles.clamp(1, view.height);
126 final rowsPer = (view.height / count).ceil();
127
128 final futures = <Future<Uint8List>>[];
129 for (var t = 0; t < count; t++) {
130 final y0 = t * rowsPer;
131 final y1 = ((t + 1) * rowsPer).clamp(0, view.height);
132 if (y0 >= y1) break;
133 futures.add(Isolate.run(() => renderBand(view, y0, y1)));
134 }
135
136 final bands = await Future.wait(futures);
137 final out = Uint8List(view.width * view.height * 4);
138 var offset = 0;
139 for (final band in bands) {
140 out.setRange(offset, offset + band.length, band);
141 offset += band.length;
142 }
143 return out;
144}