nandi/vflutter_ffipublic Fork 0
472eb493bac94bdcb79a38829ccca0c541256fef
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 · 141 lines · 4.2 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
Replace V with Nim 472eb49 nandithebull 8h ago24const String _libName = 'nimflutter';
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago25
26DynamicLibrary _open() {
27 if (Platform.isMacOS || Platform.isIOS) {
28 // Static archive linked into the app binary.
29 return DynamicLibrary.process();
30 }
31 if (Platform.isAndroid || Platform.isLinux) {
32 return DynamicLibrary.open('lib$_libName.so');
33 }
34 if (Platform.isWindows) {
35 return DynamicLibrary.open('$_libName.dll');
36 }
Replace V with Nim 472eb49 nandithebull 8h ago37 throw UnsupportedError('nimflutter_ffi: unsupported platform');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago38}
39
40final DynamicLibrary _lib = _open();
41
Replace V with Nim 472eb49 nandithebull 8h ago42final void Function() _nfInit =
43 _lib.lookupFunction<Void Function(), void Function()>('nf_init');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago44
Replace V with Nim 472eb49 nandithebull 8h ago45final int Function(int, int) _nfAdd =
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago46 _lib.lookupFunction<Int32 Function(Int32, Int32), int Function(int, int)>(
Replace V with Nim 472eb49 nandithebull 8h ago47 'nf_add');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago48
Replace V with Nim 472eb49 nandithebull 8h ago49final Pointer<Utf8> Function(Pointer<Utf8>) _nfGreet = _lib.lookupFunction<
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago50 Pointer<Utf8> Function(Pointer<Utf8>),
Replace V with Nim 472eb49 nandithebull 8h ago51 Pointer<Utf8> Function(Pointer<Utf8>)>('nf_greet');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago52
Replace V with Nim 472eb49 nandithebull 8h ago53final void Function(Pointer<Void>) _nfFree = _lib.lookupFunction<
54 Void Function(Pointer<Void>), void Function(Pointer<Void>)>('nf_free');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago55
56final void Function(Pointer<Uint8>, int, int, int, double, double, double, int,
Replace V with Nim 472eb49 nandithebull 8h ago57 int, int) _nfMandelbrot = _lib.lookupFunction<
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago58 Void Function(Pointer<Uint8>, Size, Int32, Int32, Double, Double,
59 Double, Int32, Int32, Int32),
60 void Function(Pointer<Uint8>, int, int, int, double, double, double,
Replace V with Nim 472eb49 nandithebull 8h ago61 int, int, int)>('nf_mandelbrot');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago62
63bool _ready = false;
64
65bool get isInitialized => _ready;
66
67/// Loading a shared object is synchronous, so this is only here to match the
68/// web backend's contract. Nothing awaits anything.
69Future<void> initialize() async => ensureInitialized();
70
71void ensureInitialized() {
72 if (_ready) return;
Replace V with Nim 472eb49 nandithebull 8h ago73 _nfInit();
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago74 _ready = true;
75}
76
77int add(int a, int b) {
78 ensureInitialized();
Replace V with Nim 472eb49 nandithebull 8h ago79 return _nfAdd(a, b);
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago80}
81
82String greet(String name) {
83 ensureInitialized();
84 final arg = name.toNativeUtf8();
85 Pointer<Utf8> res = nullptr;
86 try {
Replace V with Nim 472eb49 nandithebull 8h ago87 res = _nfGreet(arg);
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago88 if (res == nullptr) {
Replace V with Nim 472eb49 nandithebull 8h ago89 throw StateError('nf_greet returned null');
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago90 }
91 return res.toDartString();
92 } finally {
93 calloc.free(arg);
Replace V with Nim 472eb49 nandithebull 8h ago94 if (res != nullptr) _nfFree(res.cast());
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago95 }
96}
97
98Future<String> greetAsync(String name) => Isolate.run(() => greet(name));
99
100Uint8List renderBand(FractalView view, int y0, int y1) {
101 ensureInitialized();
102 final rows = y1 - y0;
103 if (rows <= 0) return Uint8List(0);
104
105 final bytes = rows * view.width * 4;
106 final buf = calloc<Uint8>(bytes);
107 try {
Replace V with Nim 472eb49 nandithebull 8h ago108 // `bytes` is the real allocation size, not a restatement of the band: Nim
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago109 // checks it before writing, so an arithmetic slip here is caught there
110 // rather than becoming a heap overflow.
Replace V with Nim 472eb49 nandithebull 8h ago111 _nfMandelbrot(buf, bytes, view.width, view.height, view.centerX,
Add a WebAssembly backend for the example 728acaa nandithebull 8h ago112 view.centerY, view.scale, view.maxIter, y0, y1);
113 // Copy out of native memory before it is freed.
114 return Uint8List.fromList(buf.asTypedList(bytes));
115 } finally {
116 calloc.free(buf);
117 }
118}
119
120Future<Uint8List> renderParallel(FractalView view, int tiles) async {
121 ensureInitialized();
122 final count = tiles.clamp(1, view.height);
123 final rowsPer = (view.height / count).ceil();
124
125 final futures = <Future<Uint8List>>[];
126 for (var t = 0; t < count; t++) {
127 final y0 = t * rowsPer;
128 final y1 = ((t + 1) * rowsPer).clamp(0, view.height);
129 if (y0 >= y1) break;
130 futures.add(Isolate.run(() => renderBand(view, y0, y1)));
131 }
132
133 final bands = await Future.wait(futures);
134 final out = Uint8List(view.width * view.height * 4);
135 var offset = 0;
136 for (final band in bands) {
137 out.setRange(offset, offset + band.length, band);
138 offset += band.length;
139 }
140 return out;
141}