commit 5839e270c710a2349b3ef9f8891517a87852527c
parent 7f0772f4b67fcae9fea06db4033937d69e215b04
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Sun, 25 Jun 2023 18:57:19 +0200
FFI *seems* to be working, need to work out async stuff; added example async code
Diffstat:
10 files changed, 169 insertions(+), 147 deletions(-)
diff --git a/Makefile b/Makefile
@@ -32,7 +32,7 @@ nissy_flutter_ffi: tables
cp src/* nissy_flutter_ffi/src/
cd nissy_flutter_ffi && \
flutter pub run ffigen --config ffigen.yaml
- cp tables nissy_flutter_ffi/data/
+ cp tables nissy_flutter/data/
nissy: clean nissy_flutter nissy_flutter_ffi
diff --git a/TODO.md b/TODO.md
@@ -1,6 +1,5 @@
-* Figure out FFI: long-running stuff with await?
-* Read data file from flutter and pass it to C backend
-* show EOs in gui (for example scramble)
+* Learn async stuff
+* start with example hard-coded scramble, EO only
* input text box for scramble, get EOs for that
* UI design
* other steps
diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart
@@ -1,70 +1,116 @@
+import 'dart:typed_data';
+import 'dart:async';
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart' show rootBundle;
+
+import 'package:nissy_flutter_ffi/nissy_flutter_ffi.dart' as nissy_flutter_ffi;
void main() {
- runApp(const NissyApp());
+ runApp(const MyApp());
+}
+
+class MyApp extends StatefulWidget {
+ const MyApp({super.key});
+
+ @override
+ State<MyApp> createState() => _MyAppState();
}
-class NissyApp extends StatelessWidget {
- const NissyApp({super.key});
+class _MyAppState extends State<MyApp> {
+ @override
+
+ void initState() {
+ super.initState();
+ }
@override
Widget build(BuildContext context) {
+ const textStyle = TextStyle(fontSize: 25);
+ const spacerSmall = SizedBox(height: 10);
return MaterialApp(
- title: 'Nissy',
- theme: ThemeData(
- colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
- useMaterial3: true,
+ home: Scaffold(
+ appBar: AppBar(
+ title: const Text('Nissy ffi test run'),
+ ),
+ body: SingleChildScrollView(
+ child: Container(
+ padding: const EdgeInsets.all(10),
+ child: NissyFutureBuilder(),
+ ),
+ ),
),
- home: const MyHomePage(title: 'Nissy'),
);
}
}
-class MyHomePage extends StatefulWidget {
- const MyHomePage({super.key, required this.title});
-
- final String title;
+class NissyFutureBuilder extends StatefulWidget {
+ const NissyFutureBuilder({super.key});
@override
- State<MyHomePage> createState() => _MyHomePageState();
+ State<NissyFutureBuilder> createState() => NissyFutureBuilderState();
}
-class _MyHomePageState extends State<MyHomePage> {
- int _counter = 0;
- void _incrementCounter() {
- setState(() {
- _counter++;
- });
- }
+// Copied from https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
+class NissyFutureBuilderState extends State<NissyFutureBuilder> {
+ final Future<String> _calculation = Future<String>.delayed(
+ const Duration(seconds: 2),
+ () => 'Data Loaded',
+ );
@override
Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- backgroundColor: _counter % 3 == 0 ?
- Theme.of(context).colorScheme.inversePrimary :
- Theme.of(context).colorScheme.primary,
- title: Text(widget.title),
- ),
- body: Center(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- const Text(
- 'You have pushed the button this many times:',
- ),
- Text(
- '$_counter',
- style: Theme.of(context).textTheme.headlineMedium,
+ return DefaultTextStyle(
+ style: Theme.of(context).textTheme.displayMedium!,
+ textAlign: TextAlign.center,
+ child: FutureBuilder<String>(
+ future: _calculation, // a previously-obtained Future<String> or null
+ builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
+ List<Widget> children;
+ if (snapshot.hasData) {
+ children = <Widget>[
+ const Icon(
+ Icons.check_circle_outline,
+ color: Colors.green,
+ size: 60,
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 16),
+ child: Text('Result: ${snapshot.data}'),
+ ),
+ ];
+ } else if (snapshot.hasError) {
+ children = <Widget>[
+ const Icon(
+ Icons.error_outline,
+ color: Colors.red,
+ size: 60,
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 16),
+ child: Text('Error: ${snapshot.error}'),
+ ),
+ ];
+ } else {
+ children = const <Widget>[
+ SizedBox(
+ width: 60,
+ height: 60,
+ child: CircularProgressIndicator(),
+ ),
+ Padding(
+ padding: EdgeInsets.only(top: 16),
+ child: Text('Awaiting result...'),
+ ),
+ ];
+ }
+ return Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: children,
),
- ],
- ),
- ),
- floatingActionButton: FloatingActionButton(
- onPressed: _incrementCounter,
- tooltip: 'Increment',
- child: const Icon(Icons.add),
+ );
+ },
),
);
}
diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml
@@ -1,25 +1,31 @@
-name: nissy_flutter
-description: Flutter UI for nissy-fmc
-
+name: nissy_flutter_ffi_example
+description: Demonstrates how to use the nissy_flutter_ffi plugin.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
-version: 3.0.0
+version: 1.0.0+1
environment:
- sdk: '>=3.0.1 <4.0.0'
+ sdk: '>=3.0.5 <4.0.0'
dependencies:
flutter:
sdk: flutter
- # The following adds the Cupertino Icons font to your application.
- # Use with the CupertinoIcons class for iOS style icons.
+ nissy_flutter_ffi:
+ path: ../nissy_flutter_ffi
+
+ ffi: ^1.0.0
+
cupertino_icons: ^1.0.2
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ flutter_lints: ^2.0.0
+
flutter:
uses-material-design: true
- # To add assets to your application, add an assets section, like this:
- # assets:
- # - images/a_dot_burr.jpeg
- # - images/a_dot_ham.jpeg
+ assets:
+ - data/
diff --git a/flutter_ffi/example/lib/main.dart b/flutter_ffi/example/lib/main.dart
@@ -1,55 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:nissy_flutter_ffi/nissy_flutter_ffi.dart' as nissy_flutter_ffi;
-
-void main() {
- runApp(const MyApp());
-}
-
-class MyApp extends StatefulWidget {
- const MyApp({super.key});
-
- @override
- State<MyApp> createState() => _MyAppState();
-}
-
-class _MyAppState extends State<MyApp> {
- @override
- final response = nissy_flutter_ffi.nissy_test();
- void initState() {
- super.initState();
- }
-
- @override
- Widget build(BuildContext context) {
- const textStyle = TextStyle(fontSize: 25);
- const spacerSmall = SizedBox(height: 10);
- return MaterialApp(
- home: Scaffold(
- appBar: AppBar(
- title: const Text('Nissy ffi test run'),
- ),
- body: SingleChildScrollView(
- child: Container(
- padding: const EdgeInsets.all(10),
- child: Column(
- children: [
- const Text(
- 'Calling a nissy function from nissy.h',
- style: textStyle,
- textAlign: TextAlign.center,
- ),
- spacerSmall,
- Text(
- 'Response: $response',
- style: textStyle,
- textAlign: TextAlign.center,
- ),
- ],
- ),
- ),
- ),
- ),
- );
- }
-}
diff --git a/flutter_ffi/example/pubspec.yaml b/flutter_ffi/example/pubspec.yaml
@@ -1,28 +0,0 @@
-name: nissy_flutter_ffi_example
-description: Demonstrates how to use the nissy_flutter_ffi plugin.
-publish_to: 'none' # Remove this line if you wish to publish to pub.dev
-
-version: 1.0.0+1
-
-environment:
- sdk: '>=3.0.5 <4.0.0'
-
-dependencies:
- flutter:
- sdk: flutter
-
- nissy_flutter_ffi:
- path: ../
-
- ffi: ^1.0.0
-
- cupertino_icons: ^1.0.2
-
-dev_dependencies:
- flutter_test:
- sdk: flutter
-
- flutter_lints: ^2.0.0
-
-flutter:
- uses-material-design: true
diff --git a/flutter_ffi/lib/nissy_flutter_ffi.dart b/flutter_ffi/lib/nissy_flutter_ffi.dart
@@ -2,11 +2,34 @@ import 'dart:async';
import 'dart:ffi';
import 'dart:io';
import 'dart:isolate';
+import 'dart:typed_data';
+import 'package:flutter/services.dart';
import 'package:ffi/ffi.dart';
import 'nissy_flutter_ffi_bindings_generated.dart';
+void nissy_init(ByteData tables) {
+ // Copy tables to C ffi heap, pass to actual nissy_init()
+ final tablesList = tables.buffer.asUint8List();
+ final n = tablesList.lengthInBytes;
+ final tablesHeap = calloc<Char>(n);
+ for (var i = 0; i < n; i++) {
+ tablesHeap[i] = tablesList[i];
+ }
+ _bindings.nissy_init(tablesHeap);
+}
+
String ptrCharToString(Pointer<Char> ptr) => ptr.cast<Utf8>().toDartString();
+Pointer<Char> stringToPtrChar(String str) {
+ final n = str.length;
+ final strNative = str.toNativeUtf8().cast<Char>();
+ final ptr = calloc<Char>(n+10);
+ for (var i = 0; i < n; i++) {
+ ptr[i] = strNative[i];
+ }
+ ptr[n] = 0;
+ return ptr;
+}
String nissy_test() {
final ptr = calloc<Char>(50);
@@ -16,6 +39,31 @@ String nissy_test() {
return str;
}
+List<String> nissy_eos_in(String scr, int n) {
+ var ret = List<String>.empty(growable: true);
+
+ final scramble = stringToPtrChar(scr);
+ final eofb = stringToPtrChar('eofb');
+ final uf = stringToPtrChar('uf');
+ final normal = stringToPtrChar('normal');
+
+ print('Doing thing...');
+
+ var bufferPtr = calloc<Char>(5000); // hope it is enough
+ final nsols = _bindings.nissy_solve(eofb, uf, n, normal, scramble, bufferPtr);
+ ret.add(ptrCharToString(bufferPtr));
+
+ print('Ret 0: ' + ret[0]);
+
+ calloc.free(bufferPtr);
+ calloc.free(normal);
+ calloc.free(uf);
+ calloc.free(eofb);
+ calloc.free(scramble);
+
+ return ret;
+}
+
const String _libName = 'nissy_flutter_ffi';
/// The dynamic library in which the symbols for [NissyFlutterFfiBindings] can be found.
diff --git a/flutter_ffi/pubspec.yaml b/flutter_ffi/pubspec.yaml
@@ -31,6 +31,3 @@ flutter:
ffiPlugin: true
windows:
ffiPlugin: true
-
- assets:
- - data/
diff --git a/src/nissy.c b/src/nissy.c
@@ -91,7 +91,9 @@ nissy_solve(char *step, char *trans, int d, char *type, char *scramble, char *so
if (!set_solutiontype(type, &st)) return 4;
if (!apply_scramble(scramble, &c)) return 5;
- return solve(s, t, d, st, &c, sol);
+ sol[0] = 'h'; sol[1] = 'e'; sol[2] = 'l'; sol[3] = 'o'; sol[5] = 0;
+ return 0;
+ //return solve(s, t, d, st, &c, sol);
}
void
diff --git a/src/nissy.h b/src/nissy.h
@@ -8,4 +8,11 @@ void nissy_init(char *);
void nissy_test(char *);
/* Returns 0 on success, 1-based index of bad arg on failure */
-int nissy_solve(char *s, char *trans, int d, char *type, char *scr, char *sol);
+int nissy_solve(
+ char *step, /* "eofb" */
+ char *trans, /* "uf" or similar */
+ int depth, /* Number of moves */
+ char *type, /* "normal" or "inverse" or "niss" */
+ char *scr, /* The scramble */
+ char *sol /* The solution, as a single string, \n-separated */
+);