-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[vm/ffi] clarify DynamicLibrary executable and process #44856
Comments
Hi dcharkes, I've been studying external library management lately and I've read a lot of your interesting posts and I congratulate you on your work. I'm sticking to this post, hoping not to go OT and get some answers. In my SDK (shown below) I don't yet have an argument like Part A: DartAfter calling the native library with:
I see with So if I can see in I can get response from the native function using the For example, if the function is
No problem both ways. Part B: FlutterWhen I'm in Flutter workspace, using the Android platform in debug mode, things change and after loading the native library with:
see the following differences:
My goal (not final but partial) is to understand how to use I think in this case the symbols are no longer global. I know that Is there a way to be able to do this by acting on the Dart code, native code, CMakeLists,txt or elsewhere to correctly compile the external functions and/or have the symbols globally? Thank you. Flutter 3.7.3 • stable channel • Dart 2.19.2 |
MacOS and Linux open with GLOBAL, while Android does not. That explains the difference between the Flutter and Dart experience. Flutter Desktop should also work with GLOBAL. The workaround is to call /// On Linux and Android.
const RTLD_LAZY = 0x00001;
/// On Android Arm.
const RTLD_GLOBAL_android_arm32 = 0x00002;
/// On Linux and Android Arm64.
const RTLD_GLOBAL_rest = 0x00100;
final RTLD_GLOBAL = Abi.current() == Abi.androidArm
? RTLD_GLOBAL_android_arm32
: RTLD_GLOBAL_rest;
@Native<Pointer<Void> Function(Pointer<Char>, Int)>()
external Pointer<Void> dlopen(Pointer<Char> file, int mode);
/// Returns dylib
Object dlopenGlobalPlatformSpecific(String name, {String? path}) {
if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia) {
// TODO(https://dartbug.com/50105): enable dlopen global via package:ffi.
return using((arena) {
final dylibHandle = dlopen(
platformPath(name).toNativeUtf8(allocator: arena).cast(),
RTLD_LAZY | RTLD_GLOBAL);
return dylibHandle;
});
} else {
// The default behavior on these platforms is RLTD_GLOBAL already.
return dlopenPlatformSpecific(name, path: path);
}
} In the future, you will be able to use |
Thanks for your fast reply. As often happens, an answer brings other doubts with it and, after having tried to resolve them on my own, I think it is appropriate that I ask you some questions (even basic ones) to dispel them. I state that I am about to release an app and I would like to avoid changing SDK versions at this moment or prepare for the use of SDK manager, leaving the thing to other moments in which I can test the work environment more serenely . I remember that at the moment I'm using this configuration: Flutter 3.7.3 • stable channel • Dart 2.19.2. Here are some statements and questions for you to check.
The following error is returned:
But although in Android this does not throw an error with the dlopen it returns an handle with But with the Windows platform (which shouldn't be affected given the premises but I used it as a test) the behavior is different and directly returns an error.
I tried to add via
Although Too bad that even with the correct path to pass to
I look forward to your instructions in order to successfully start the script. |
Regarding points 8-9 I opened a new problem to analyze it individually and even if I understood the main problem I also have to understand how to solve it. |
The other two you'll have to define yourself, for your convenience: String platformPath(String name, {String path = ""}) {
if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
return path + "lib" + name + ".so";
if (Platform.isMacOS) return path + "lib" + name + ".dylib";
if (Platform.isWindows) return path + name + ".dll";
throw Exception("Platform not implemented");
}
Only in the one invocation. (Dart experiments are per invocation. Flutter experiments are global and persisted. So once native assets are available there it will be a persisted setting.)
It's available
If you can call it, you should be able to use it. Maybe you're passing the wrong path to the dynamic library or the wrong flags.
Windows has a different API and does not use |
Yes, as written previously I used
Yes, as stated and indicated in my comments, for a correct analysis, I use Dart 2.19.2. In my version Anyway this in my case shouldn't make any difference because the native function is also found with |
Correct, |
We have two factory constructors in
DynamicLibrary
,process
andexecutable
, which currently have identical behavior. They can lookup symbols in the executable and statically linked libraries, but not dynamically linked libraries.(x)They would behave differently if
DynamicLibrart.open
would load a library with global visibility instead of local visibility. In that caseDynamicLibrart.process
would be able to see the symbols, butDynamicLibrart.executable
would not.We could do one of the following:
DynamicLibrary.process
and always useDynamicLibrary.executable
. (DynamicLibrary.process
is not available on Windows,DynamicLibrary.executable
is.)DynamicLibrary.open
to enable loading a library with global visibility by adding a named argument.(x) One can do a lookup of
dlopen
, and thendlopen
with global visibility. That would make the symbol visible inDynamicLibrart.process
.Some experiments: https://dart-review.googlesource.com/c/sdk/+/182629. On the various OSes we have different behavior.
The text was updated successfully, but these errors were encountered: