3

I am working on a flutter project that runs fine in development. However I do not know how to get the build to include dll's referenced using FFI.

I can't find clear instructions on how to do it.

I tried following the steps to build an msix here, which worked but didn't seem to include the dll (it fails in the same way as the regular build)

what is the procedure to have the build process consider the dll's?

other dll's show up in the build directory from 3rd party packages so there must be a way right?

xerotolerant
  • 1,955
  • 4
  • 21
  • 39

2 Answers2

3

That's really hard to discover by your own, but indeed you can bind those libraries to you MSIX. In my case I just made a package for label printers using Dart FFI and DLL`s provided by manufacturer and this is how I did it.

You need to add these DLL's to your assets setting on pubspec.yaml from your package. This is my case:

[...]
flutter:
  [...]
  assets:
    - assets/WinPort.dll
    - assets/Winppla.dll
    - assets/Winpplb.dll
    - assets/Winpplz.dll

With this setting you will embed your DLL files in your final MSIX, but this was the easy part. Now you have make sure to load the proper load these files in code. Based on my own tests, I still dealing with two ways to develop and test code, the first one is when I am running a project in my machine via flutter run I must set the target for current.path, when I get it done and start building for deploy I change this to resolvedExecutable.parent.path. Where is what you need to do. Loading you DLL in development environment (flutter run):

final String _packageAssetsDirPath = normalize(join(Directory.current.path,'assets'));

On production environment (running from .exe or MSIX installed):

final String _assetsPackageDir = normalize(
      join('data', 'flutter_assets', 'packages', 'YOUR_PACKAGE_NAME', 'assets'));
  final String _exeDirPath = File(Platform.resolvedExecutable).parent.path;
  final String _packageAssetsDirPath =
      normalize(join(_exeDirPath, _assetsPackageDir));

After with this var called _packageAssetsDirPath will be easy to load your DLL's, now you invoke a DynamicLibrary constructor:

// Path for DLL file
final String _libDllSourceFullPath =
      normalize(join(_packageAssetsDirPath, 'Winppla.dll'));
// Target for copy, place DLL in same place the .exe you are running
final String _libDllDestFullPath =
      normalize(join(_packageAssetsDirPath, 'YOUROWN.dll'));
// Try to copy for running exe path
File(_libDllSourceFullPath).copySync(_libDllDestFullPath);

// With this copy, would be simple to load, and if it fails, try in full path
// LOAD DLL
  try {
    String _packageAssetsDirPath =
        normalize(join(Directory.current.path, 'assets'));
    String _printerLibraryPath =
        normalize(join(_packageAssetsDirPath, 'Winppla.dll'));

    DynamicLibrary _library = DynamicLibrary.open(_printerLibraryPath);
    return _library;
  } catch (e) {
    try {
      DynamicLibrary _library = DynamicLibrary.open('Winppla.dll');
      return _library;
    } catch (e) {
      // Avoing errors creating a fake DLL, but you could deal with an exception
      return DynamicLibrary.process();

    }
  }

At this point you can load a DLL and use it, you can check my package full code at https://github.com/saviobatista/argox_printer check for lib/src/ppla.dart at function _setupDll() and you will see that loading.

Sávio Batista
  • 124
  • 1
  • 7
  • I think you're safe here since this answer provides substantive detail that's not dependent upon your own package, but do be sure to refer to [Stack Overflow's self-promotion policy](https://stackoverflow.com/help/promotion) when referencing your own content just to make sure you're staying within those boundaries. – Jeremy Caney Mar 08 '22 at 00:26
  • Have you tried distributing your app to another PC? I have followed your example and it works like a charm on my machine. However, when I share the MSIX file to install on another PC, the testers still are getting the error that the DLL cannot be found at path C:\Program Files\WindowsApps\MY_APP_BUNDLE_ID\data\flutter_assets\packages\MY_PACKAGE_NAME\MY.dll Does it work for you, when you distribute your app to a different machine? – Volodymyr Lymar Jun 02 '23 at 15:47
  • 1
    @VolodymyrLymar indeed I had issues with MSIX for packaging the software, but when I packed as ZIP and installed the runtime it worked fine. It seems to be a limitation of MSIX deployment with flutter, I suggest you to create an issue on repository and then It can be further investigated. – Sávio Batista Jun 03 '23 at 08:53
3

I built a simpler option inspired in the solution of Sávio Batista

(You must have your .dll in your assets folder)

if (kReleaseMode) {
    // I'm on release mode, absolute linking
    final String local_lib =  join('data',  'flutter_assets', 'assets', 'libturbojpeg.dll');
    String pathToLib = join(Directory(Platform.resolvedExecutable).parent.path, local_lib);
    DynamicLibrary lib = DynamicLibrary.open(pathToLib);
  } else {
    // I'm on debug mode, local linking
    var path = Directory.current.path;
    DynamicLibrary lib = DynamicLibrary.open('$path/assets/libturbojpeg.dll');
  }

Just replace libturbojpeg.dll for your .dll

Javier
  • 647
  • 1
  • 7
  • 30