You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Linux下通过MinGW交叉编译Dart FFI库后,Wine无法正确加载生成的.dll文件的问题排查

Linux下通过MinGW交叉编译Dart FFI库后,Wine无法正确加载生成的.dll文件的问题排查

问题核心梳理

你现在遇到的问题是两个关键错误叠加导致的:

  1. Dart AOT编译的平台误解:在Linux上用dart compile exe生成的app.exe其实是Linux原生的ELF可执行文件(只是后缀改了.exe),并非Windows的PE格式程序,Wine根本无法正确运行Linux原生程序;
  2. 库加载逻辑的判断失效:你的代码依赖WINELOADERNOEXEC这个非默认环境变量来识别Wine环境,但这个变量默认不会被自动设置,导致代码直接进入Linux分支,去寻找不存在的.so文件。

分步解决方案

第一步:先搞定真正的Windows Dart EXE编译

Dart目前不支持跨平台AOT编译(没法在Linux上直接编译出Windows PE格式的exe),你有两个靠谱方案:

方案A:用Wine运行Windows版Dart SDK编译

  1. 下载Windows版Dart SDK到Linux本地目录(比如~/dart-win-sdk
  2. 用Wine调用Windows版dart.exe生成真正的Windows可执行文件:
    wine ~/dart-win-sdk/bin/dart.exe compile exe ../bin/main.dart -o app.exe
    
    这样生成的app.exe才是Wine能识别的Windows格式程序。

方案B:在Windows环境下编译(物理机/虚拟机/容器)

直接在Windows系统里完成Dart exe的编译,再把生成的app.exe和你交叉编译好的MyNativeLib.dll放在同一目录,拷贝到Linux上用Wine运行。

第二步:修复Dart代码的库加载逻辑

原来的判断依赖冷门环境变量,可靠性极低,改成更通用的逻辑:

  • 只要是Windows平台(不管原生Windows还是Wine模拟的),直接加载.dll
  • 也可以用命令行参数强制指定库路径,灵活性更高。

修改后的openLibrary()函数示例:

ffi.DynamicLibrary openLibrary() {
  final currentDir = Directory.current.path;

  // 推荐:直接根据目标平台判断(Wine下运行Windows exe时,Platform.isWindows会返回true)
  if (Platform.isWindows) {
    return ffi.DynamicLibrary.open(p.join(currentDir, 'MyNativeLib.dll'));
  } else if (Platform.isLinux) {
    return ffi.DynamicLibrary.open(p.join(currentDir, 'build-linux', 'libMyNativeLib.so'));
  } else if (Platform.isMacOS) {
    return ffi.DynamicLibrary.open(p.join(currentDir, 'build-macos', 'libMyNativeLib.dylib'));
  } else {
    throw UnsupportedError('Unsupported platform');
  }

  // 可选:用命令行参数/环境变量指定库路径,适合调试
  // final libPath = Platform.environment['NATIVE_LIB_PATH'] ?? p.join(currentDir, 'MyNativeLib.dll');
  // return ffi.DynamicLibrary.open(libPath);
}

第三步:正确的运行验证步骤

  1. 把交叉编译好的MyNativeLib.dll和真正的Windows版app.exe放在同一目录
  2. 切换到该目录,用Wine运行程序:
    cd build-mingw
    wine app.exe
    

额外实用提示

  1. Wine路径问题:Wine会把Linux目录映射为Windows的Z盘(比如/home/xxx/build-mingw对应Z:\home\xxx\build-mingw),Dart的Directory.current会自动适配路径,所以相对路径加载完全没问题;
  2. DLL依赖检查:如果提示找不到依赖库,用MinGW的工具检查:
    x86_64-w64-mingw32-ldd MyNativeLib.dll
    
  3. 符号导出验证:确认你的DLL正确导出了say_hello函数:
    x86_64-w64-mingw32-nm -D MyNativeLib.dll | grep say_hello
    

最后排查小技巧

如果还是报错找不到DLL:

  • wine cmd /c dir查看Wine当前目录的文件,确认MyNativeLib.dll存在;
  • 检查CMake是否正确去掉了lib前缀(你的配置里已经加了set_target_properties(MyNativeLib PROPERTIES PREFIX ""),这步是对的);
  • 确认DLL的架构和Dart exe一致(都是x64,因为你用的是x86_64-w64-mingw32工具链)。

火山引擎 最新活动