最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Flutter crashes on use of Evolis android SDK with ffi - Stack Overflow

programmeradmin5浏览0评论

This is a very specific question, but I don't know where to search anymore.

I am a Flutter developer and want to print plastic cards with an evolis Primecy 2 printer. Evlois does provide an SDK for android in the form of .so files. .html .html

I added the files to the correct folders in my android directory and generated the dart binding class via ffigen. So I can access the SDK. It also works for the function 'evolis_version'. That gives me the version 9.0.2.6484.

But when I try to call evolis_open() as the first link suggests, the app crashes. I do not catch an exception, it just crashes. I can look up the function, so it does exist.

The crash logs:

F/libc    (22120): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 22155 (1.ui), pid 22120 (systems.test_app)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'SUNMI/V3_MIX_EDLA_GL/V3_MIX:13/TKQ1.230110.001/40:user/release-keys'
Revision: '0'
ABI: 'arm64'
Timestamp: 2025-02-19 14:58:37.674946211+0100
Process uptime: 36s
Cmdline: deanisation.test_app
pid: 22120, tid: 22155, name: 1.ui  >>> deanisation.test_app <<<
uid: 10158
tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0000000000000000
Cause: null pointer dereference
    x0  0000000000000000  x1  0000006e536adaf8  x2  0000006e536adaf8  x3  0000000000000010
    x4  0000000000000000  x5  0000cd860000ce6a  x6  0000cd860000ce6a  x7  0000cd680000cde6
    x8  f546e016fd83d64d  x9  f546e016fd83d64d  x10 000000000000568b  x11 0000006e7b9ff8d0
    x12 000000002acdb8f0  x13 0000000000000000  x14 00000000ffffffee  x15 0000000000000000
    x16 0000000000004000  x17 0000000000000000  x18 0000006e7b49a000  x19 0000006e52bd9e75
    x20 0000006e52bd83be  x21 0000006e52bd4116  x22 0000000000000000  x23 0000006e7ba01000
    x24 0000006e536ad000  x25 0000006e7b9ff788  x26 b400006f2acdb8d0  x27 0000006e7b9ff8c8
    x28 0000006e7b9ff760  x29 0000006e7b9ff3d0
    lr  0000006e52efe80c  sp  0000006e7b9ff3b0  pc  0000006e52efe80c  pst 0000000060000000
backtrace:
      #00 pc 00000000004df80c  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (_jobject* evolis::JniUtils::getStaticField<_jobject*>(char const*, char const*, char const*)+124) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #01 pc 00000000004de33c  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis::AndroidUtils::forEachUsbDevice(std::__ndk1::function<void (_jobject*)> const&)+72) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #02 pc 00000000004dca98  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis::AndroidUsbDeviceEnumerator::enumerate() const+72) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #03 pc 0000000000356598  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis::DeviceFinder::findOne(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, evolis::DeviceEnumerator*)+76) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #04 pc 0000000000356454  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis::DeviceFinder::findOne(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&)+184) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #05 pc 000000000033986c  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis::Connection::build(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, evolis_open_mode_e)+176) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #06 pc 000000000032eae0  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis::Context::open(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, evolis_open_mode_e)+40) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #07 pc 0000000000325c14  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis_open_with_mode+316) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #08 pc 0000000000325a9c  /data/app/~~ATq07aqcr-JzX4yJnAR9lA==/deanisation.test_app-E6AIbCnKYHRpd1L8A3nZeA==/base.apk!libevolis.so (evolis_open+152) (BuildId: dc922624b7361818e45e46a577d9045ca4b9bc3b)
      #09 pc 0000000000008264  [anon:dart-code]
Lost connection to device.
the Dart compiler exited unexpectedly.

The APK does contain the .so files, so that should not be a problem.

At this point, I don't know what else can I test. Is someone here who knows how to access this SDK?

% flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.27.2, on macOS 15.1.1 24B91 darwin-arm64, locale de-DE)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
[!] Xcode - develop for iOS and macOS (Xcode 16.1)
    ✗ Unable to get list of installed Simulator runtimes.
    ✗ CocoaPods not installed.
        CocoaPods is a package manager for iOS or macOS platform code.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see /to/platform-plugins
      For installation instructions, see .html#installation
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.1)
[✓] IntelliJ IDEA Ultimate Edition (version 2024.1.7)
[✓] VS Code (version 1.97.2)
[✓] Connected device (4 available)
[✓] Network resources

Here is how I call the function:

import 'dart:ffi' as ffi;
import 'dart:io';

import 'package:ffi/ffi.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:pos_app/ffi_libs/generated_evolis_bindings.dart';
import 'package:pos_app/utility/widgets/space.dart';

class EvoilsTestPage extends StatefulWidget {
  const EvoilsTestPage({super.key});

  @override
  State<EvoilsTestPage> createState() => _EvoilsTestPageState();
}

class _EvoilsTestPageState extends State<EvoilsTestPage> {
  late final EvolisBindings evoBinding;
  String status = 'ready';

  @override
  void initState() {
    if (!kIsWeb) {
      final dynamicLibrary = Platform.isAndroid
          ? ffi.DynamicLibrary.open('libevolis.so')
          : ffi.DynamicLibrary.process();
      evoBinding = EvolisBindings(dynamicLibrary);
    }
    super.initState();
  }

  updateStatus(String status) {
    print(status);
    setState(() {
      this.status = status;
    });
  }

  _getEvoVersion() {
    try {
      final versionPtr = evoBinding.evolis_version();
      String version = versionPtr.cast<Utf8>().toDartString();
      updateStatus("evo version: $version");
    } catch (e) {
      updateStatus("evolis_version function NOT found: $e");
    }
  }

  _lookUpFunction() {
    String functionName = "evolis_open";
    try {
      updateStatus("start Print");
      updateStatus("openPrinter");
      final openFunc = evoBinding.lookup("evolis_open");
      updateStatus('$functionName: ${openFunc.toString()}');
      return;
    } catch (e) {
      updateStatus('$functionName does not seem to exist:\n\n${e.toString()}');
    }
  }

  _testPrint() async {
    ffi.Pointer<ffi.Char> namePtr = ffi.nullptr;
    try {
      String dartString = 'Evolis Primacy 2';
      namePtr = dartString.toNativeUtf8().cast<ffi.Char>();

      final printerPtr = evoBinding.evolis_open(namePtr);

      if (printerPtr.address == 0) {
        updateStatus("Failed to open printer.");
      } else {
        updateStatus(
            "Printer opened successfully. ${printerPtr.toString()}");
      }
      print("closePrinter");
      evoBinding.evolis_close(printerPtr);
      print("free pointer");
      malloc.free(namePtr);
    } catch (e) {
      malloc.free(namePtr);
      updateStatus(e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Evolis Printer Test")),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(status),
            Space.p40(),
            ElevatedButton(
              onPressed: () => _testPrint(),
              child: Text("Test Print"),
            ),
            ElevatedButton(
              onPressed: _getEvoVersion,
              child: Text("Evo Version"),
            ),
            ElevatedButton(
              onPressed: _lookUpFunction,
              child: Text("Lookup Function"),
            ),
          ],
        ),
      ),
    );
  }
}


I wont throw the generated class in here because it is 14495 lines. But here is the important functions call

import 'dart:ffi' as ffi;

class EvolisBindings {
  /// Holds the symbol lookup function.
  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
      lookup;

  /// The symbols are looked up in [dynamicLibrary].
  EvolisBindings(ffi.DynamicLibrary dynamicLibrary)
      : lookup = dynamicLibrary.lookup;

  /// The symbols are looked up with [lookup].
  EvolisBindings.fromLookup(
      ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
          lookup)
      : lookup = lookup;

  /// Connect to the printer referenced by the `name` argument.
  /// Same as evolis_open_with_mode(a, EVOLIS_OM_AUTO)
  ffi.Pointer<evolis_t> evolis_open(
    ffi.Pointer<ffi.Char> name,
  ) {
    return _evolis_open(
      name,
    );
  }

  late final _evolis_openPtr = lookup<
      ffi.NativeFunction<
          ffi.Pointer<evolis_t> Function(
              ffi.Pointer<ffi.Char>)>>('evolis_open');
  late final _evolis_open = _evolis_openPtr
      .asFunction<ffi.Pointer<evolis_t> Function(ffi.Pointer<ffi.Char>)>();


        /// Get library version at runtime.
  ffi.Pointer<ffi.Char> evolis_version() {
    return _evolis_version();
  }

  late final _evolis_versionPtr =
      lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>(
          'evolis_version');
  late final _evolis_version =
      _evolis_versionPtr.asFunction<ffi.Pointer<ffi.Char> Function()>();


}
发布评论

评论列表(0)

  1. 暂无评论