如何获取Dart执行文件目录 无需用户传参访问pub包内资源
可行实现方案
下面分不同场景给出可直接落地的实现方案:
场景1:发布到pub.dev的纯Dart CLI包(非Flutter)
依托Dart生态标准配置文件即可实现路径自动查找,不需要用户传入任何参数:
- 使用Dart官方维护的
package_config包读取项目配置:所有执行过pub get的Dart/Flutter项目都会在根目录生成.dart_tool/package_config.json文件,里面记录了所有依赖包的本地存储绝对路径。
示例实现代码:
import 'package:package_config/package_config.dart'; import 'dart:io'; Future<String> getPackageDynamicLibPath() async { // 自动查找当前项目的package配置 final packageConfig = await findPackageConfig(Directory.current); if (packageConfig == null) { throw StateError('未找到package配置,请先执行pub get'); } // 替换成你自己的Dart包名 final myPackage = packageConfig.packages.firstWhere((pkg) => pkg.name == 'your_package_name'); // 拼接你包内动态库的相对路径,比如你把动态库放在包根目录的lib/dylib/下 final dylibDir = '${myPackage.root.toFilePath()}lib/dylib/'; // 根据当前平台返回对应动态库的完整路径 if (Platform.isWindows) { return '${dylibDir}your_lib.dll'; } else if (Platform.isMacOS) { return '${dylibDir}libyour_lib.dylib'; } else if (Platform.isLinux) { return '${dylibDir}libyour_lib.so'; } throw UnsupportedError('当前平台不支持'); }
该方案适配所有桌面端Dart运行环境,只要依赖你包的项目执行过pub get即可正常运行,不需要用户做额外配置。
场景2:AOT编译后单独分发的二进制文件
如果你的包最终会被编译为独立的exe/elf/macho二进制文件分发,没有package_config.json可用,使用动态库内置方案:
- 编译前将动态库读为字节数组硬编码到Dart代码中,运行时将字节写入系统临时目录再加载,完全不依赖外部路径:
示例实现代码:
import 'dart:io'; import 'dart:typed_data'; import 'dart:ffi'; // 你可以提前写个脚本把动态库文件转换成Uint8List常量代码,编译时直接嵌入到二进制中 // 以下为不同平台的动态库字节常量示例 const _windowsDylibBytes = Uint8List.fromList([/* 你的dll文件字节数组 */]); const _macosDylibBytes = Uint8List.fromList([/* 你的dylib文件字节数组 */]); const _linuxDylibBytes = Uint8List.fromList([/* 你的so文件字节数组 */]); Future<DynamicLibrary> loadDynamicLib() async { // 选择对应平台的动态库字节 final dylibBytes = Platform.isWindows ? _windowsDylibBytes : Platform.isMacOS ? _macosDylibBytes : _linuxDylibBytes; // 写入系统临时目录 final tempDir = await Directory.systemTemp.createTemp('your_package_prefix_'); final dylibPath = '${tempDir.path}/${Platform.isWindows ? 'your_lib.dll' : Platform.isMacOS ? 'libyour_lib.dylib' : 'libyour_lib.so'}'; await File(dylibPath).writeAsBytes(dylibBytes); // 加载动态库 return DynamicLibrary.open(dylibPath); }
场景3:Flutter全平台适配
如果你开发的是Flutter插件包,直接用Flutter官方的FFI插件模板创建项目即可:
- Android端:把动态库放到
android/src/main/jniLibs/下的对应ABI目录(armeabi-v7a、arm64-v8a等),加载时直接传动态库文件名,系统会自动查找路径。 - iOS端:把动态库添加到iOS插件的framework依赖中,配置好编译参数,加载时直接传文件名即可。
- 桌面端:将动态库放到对应平台的打包配置目录中,Flutter打包时会自动把动态库放到可执行文件同级目录,加载时用
'${File(Platform.resolvedExecutable).parent.path}/你的动态库文件名'拼接路径即可,该方案在Windows/Linux/macOS下均可用。
内容的提问来源于stack exchange,提问作者azan-n
相关产品推荐
相关产品推荐

