I created a fresh project using flutter create --platforms=android,ios,macos,linux,windows --template=plugin_ffi demo_ffi
I depended on it in another flutter app and used the default shipped functions sum
and sumAsync
successfully without doing any change to the ffi plugin files.
- Now I deleted the default functions and replaced them with this:
demo_ffi.cpp:
#include "demo_ffi.h"
void sayHi(){
printf("Hi from C++");
}
- I generated the bindings using ffigen, I inspected the generated file and they are generated correclty:
class DemoFfiBindings {
/// Holds the symbol lookup function.
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
_lookup;
/// The symbols are looked up in [dynamicLibrary].
DemoFfiBindings(ffi.DynamicLibrary dynamicLibrary)
: _lookup = dynamicLibrary.lookup;
/// The symbols are looked up with [lookup].
DemoFfiBindings.fromLookup(
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
lookup)
: _lookup = lookup;
void sayHi() {
return _sayHi();
}
late final _sayHiPtr =
_lookup<ffi.NativeFunction<ffi.Void Function()>>('sayHi');
late final _sayHi = _sayHiPtr.asFunction<void Function()>();
}
created a function to invoke the native code:
void sayHi() => _bindings.sayHi();
Used this function in a flutter app, but I got:
Running "flutter pub get" in example...
Launching lib\main.dart on Windows in debug mode...
Building Windows application...
Debug service listening on ws://127.0.0.1:53129/fTa9IMYDG1M=/ws
Syncing files to device Windows...
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Failed to lookup symbol 'sayHi': error code 127
#0 DynamicLibrary.lookup (dart:ffi-patch/ffi_dynamic_library_patch.dart:34:70)
#1 DemoFfiBindings._sayHiPtr (package:demo_ffi/demo_ffi_bindings_generated.dart:34:55)
#2 DemoFfiBindings._sayHiPtr (package:demo_ffi/demo_ffi_bindings_generated.dart)
#3 DemoFfiBindings._sayHi (package:demo_ffi/demo_ffi_bindings_generated.dart:35:23)
#4 DemoFfiBindings._sayHi (package:demo_ffi/demo_ffi_bindings_generated.dart)
#5 DemoFfiBindings.sayHi (package:demo_ffi/demo_ffi_bindings_generated.dart:30:12)
#6 sayHi (package:demo_ffi/demo_ffi.dart:25:27)
- I used
dumpbin -exports .\demo_ffi.dll
on the generated library file in theBuild/windows/runner/Debug
folder, and it says that the function actually exists:
dumpbin -exports .\demo_ffi.dll
Microsoft (R) COFF/PE Dumper Version 14.33.31630.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file .\demo_ffi.dll
File Type: DLL
Section contains the following exports for demo_ffi.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 000010A0 ?sayHi@@YAXXZ = @ILT+155(?sayHi@@YAXXZ)
Summary
1000 .00cfg
1000 .data
1000 .idata
1000 .pdata
3000 .rdata
1000 .reloc
1000 .rsrc
8000 .text
So why is the function not found??
Update:
As per Richard's comment, I made EXTERN "C" unconditional for all systems (windows, linux, ...)
So now demo_ffi.h:
EXTERN "C" void sayHi(); // I also tried EXTERNC
I even made sayHi
a no-op function:
demo_ffi.cpp
:
#include "image_magick_ffi.h"
void sayHi(){}
So now when I build the app that uses this plugin, I get new errors and the app won't build:
[ +61 ms] D:\dev_haidar\flutter\ffi_app_demo\windows\flutter\ephemeral\.plugin_symlinks\image_magick_ffi\src\image_magick_ffi.h(1,8): error C2143: syntax error: missing ';' before 'string' [D:\dev_haidar\flutter\ffi_app_demo\build\windows\plugins\image_magick_ffi\shared\image_magick_ffi.vcxproj]
[ +1 ms] D:\dev_haidar\flutter\ffi_app_demo\windows\flutter\ephemeral\.plugin_symlinks\image_magick_ffi\src\image_magick_ffi.h(1,8): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int [D:\dev_haidar\flutter\ffi_app_demo\build\windows\plugins\image_magick_ffi\shared\image_magick_ffi.vcxproj]
[ ] D:\dev_haidar\flutter\ffi_app_demo\windows\flutter\ephemeral\.plugin_symlinks\image_magick_ffi\src\image_magick_ffi.h(1,8): error C2143: syntax error: missing ';' before 'string' [D:\dev_haidar\flutter\ffi_app_demo\build\windows\plugins\image_magick_ffi\shared\image_magick_ffi.vcxproj]
[ ] D:\dev_haidar\flutter\ffi_app_demo\windows\flutter\ephemeral\.plugin_symlinks\image_magick_ffi\src\image_magick_ffi.h(1,8): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int [D:\dev_haidar\flutter\ffi_app_demo\build\windows\plugins\image_magick_ffi\shared\image_magick_ffi.vcxproj]
[ +23 ms] Exception: Build process failed.
[ +3 ms]
#0 throwToolExit (package:flutter_tools/src/base/common.dart:10:3)
#1 RunCommand.runCommand (package:flutter_tools/src/commands/run.dart:615:9)
<asynchronous suspension>
#2 FlutterCommand.run.<anonymous closure> (package:flutter_tools/src/runner/flutter_command.dart:1209:27)
<asynchronous suspension>
#3 AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
<asynchronous suspension>
#4 CommandRunner.runCommand (package:args/command_runner.dart:209:13)
<asynchronous suspension>
#5 FlutterCommandRunner.runCommand.<anonymous closure> (package:flutter_tools/src/runner/flutter_command_runner.dart:281:9)
<asynchronous suspension>
#6 AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
<asynchronous suspension>
#7 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:229:5)
<asynchronous suspension>
#8 run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:62:9)
<asynchronous suspension>
#9 AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
<asynchronous suspension>
#10 main (package:flutter_tools/executable.dart:91:3)
<asynchronous suspension>
Note (I renamed the project in case you wonder from the latter error logs)