| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:ffi'; | |
| import 'dart:io' show Platform; | |
| import 'package:ffi/ffi.dart'; | |
| final _dylibExtension = () { | |
| if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia) | |
| return '.so'; | |
| if (Platform.isMacOS) return '.dylib'; | |
| if (Platform.isWindows) return '.dll'; | |
| throw Exception('Platform not implemented.'); | |
| }(); | |
| final _dylibPrefix = Platform.isWindows ? '' : 'lib'; | |
| String dylibName(String name) => '$_dylibPrefix$name$_dylibExtension'; | |
| String platformPath(String name, {String? path}) { | |
| path ??= ''; | |
| return path + dylibName(name); | |
| } | |
| DynamicLibrary dlopenPlatformSpecific(String name, {String? path}) { | |
| String fullPath = platformPath(name, path: path); | |
| return DynamicLibrary.open(fullPath); | |
| } | |
| /// 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); | |
| } | |
| } |