universal_ffi 1.1.3 copy "universal_ffi: ^1.1.3" to clipboard
universal_ffi: ^1.1.3 copied to clipboard

A drop-in replacement for dart:ffi for all platforms including web (using wasm_ffi).

universal_ffi #

build_badge github_badge universal_ffi_pub_ver universal_ffi_pub_points universal_ffi_pub_popularity universal_ffi_pub_likes license_badge

universal_ffi is a wrapper on top of wasm_ffi and dart:ffi to provide a consistent API across all platforms. It also has some helper methods to make it easier to use.

wasm_ffi has a few limitations, so some of the features of dart:ffi are not supported. Most notably:

  • Array
  • Struct
  • Union

Usage #

Install #

dart pub add universal_ffi

or

flutter pub add universal_ffi

Generate binding files #

Generates bindings using package:ffigen. Replace import 'dart:ffi' as ffi; with import 'package:universal_ffi/ffi.dart' as ffi; in the generated binding files.

Using FfiHelper #

import 'package:universal_ffi/ffi.dart';
import 'package:universal_ffi/ffi_helper.dart';
import 'package:universal_ffi/ffi_utils.dart';
import 'native_example_bindings.dart';

...
  final ffiHelper = await FfiHelper.load('ModuleName');
  final bindings = WasmFfiBindings(ffiHelper.library);

  // use bindings
  using((Arena arena) {
    ...
  }, ffiHelper.library.allocator);
...

Features #

DynamicLibrary.openAsync() #

DynamicLibrary.open is synchronous for 'dart:ffi', but asynchronous for 'wasm_ffi'. This helper method uses both asynchronously.

FfiHelper.load() #

FfiHelper.load resolves the modulePath to the platform specific path in a variety of ways.

Simple usage

In the case, it is assumed that all platforms load a shared library from the same relative path. For example, if the modulePath = 'path/name', then the following paths are used:

  • Web: 'path/name.js' or 'path/name.wasm' (if isStandaloneWasm option is specified)
  • Linux & Android: 'path/name.so'
  • Windows: 'path/name.dll'
  • macOS & iOS: 'path/libname.dylib'

Option: isStaticallyLinked

If the modulePath = 'path/name' and isStaticallyLinked option is specified, then the following paths are used:

  • Web: 'path/name.js' or 'path/name.wasm' (if isStandaloneWasm option is specified)
  • All other platforms: Instead of loading a shared library, calls DynamicLibrary.process().

Option: isFfiPlugin (used for Flutter Ffi Plugin)

If the modulePath = 'path/name' and isFfiPlugin option is specified, then 'path' is ignored and the following paths are used:

  • Web: 'assets/package/name/assets/name.js' or 'assets/package/name/assets/name.wasm' (if isStandaloneWasm option is specified)
  • Linux & Android: 'name.so'
  • Windows: 'name.dll'
  • macOS & iOS: 'name.framework/name'

Overrides

Overrides can be used to specify the path to the module to be loaded for specific [AppType]. Override strings are used as is.

Multiple wasm_ffi modules in the same project

If you have multiple wasm_ffi modules in the same project, the global memory will refer only to the first loaded module. So unless the memory is explicitly specified, the memory from the first loaded module will be used for all modules, causing unexpected behavior. One option is to explicitly use library.allocator for wasm & malloc/calloc for ffi. Alternatively, you can use FfiHelper.safeUsing or FfiHelper.safeWithZoneArena:

FfiHelper.safeUsing()

FfiHelper.safeUsing is a wrapper for using. It ensures that the library-specific memory is used.

FfiHelper.safeWithZoneArena()

FfiHelper.safeWithZoneArena is a wrapper for withZoneArena. It ensures that the library-specific memory is used.


Contributions are welcome! 🚀

4
likes
160
points
332
downloads

Publisher

verified publishervm75.duckdns.org

Weekly Downloads

A drop-in replacement for dart:ffi for all platforms including web (using wasm_ffi).

Repository (GitHub)

Topics

#ffi #wasm #native #web #cross-platform

Documentation

API reference

License

MIT (license)

Dependencies

ffi, path, wasm_ffi

More

Packages that depend on universal_ffi