You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Windows平台通过CMake将C++库迁移至Flutter可执行程序

解决Windows下Flutter + Dart FFI + CMake的DLL路径与目录结构问题

针对你遇到的Windows平台DLL路径不对、Debug/Release目录分离,以及作为包被引用时的适配问题,提供以下几种可行方案:

一、修正CMake输出目录配置

Windows下DLL属于RUNTIME目标而非LIBRARY,你之前用CMAKE_LIBRARY_OUTPUT_DIRECTORY是无效的,需要改用RUNTIME_OUTPUT_DIRECTORY,同时结合Debug/Release的生成器表达式区分目录。另外,Flutter构建时会自动设置FLUTTER_BUILD_DIR变量,可适配项目作为包被引用的场景:

在你的C++库的CMakeLists.txt中添加:

if(WIN32)
  # 直接指定输出到Flutter runner的对应目录
  set_target_properties(你的C++库目标名称 PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_LIST_DIR}/../build/windows/runner/Debug"
    RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_LIST_DIR}/../build/windows/runner/Release"
  )

  # 适配项目作为包被引用的情况,使用Flutter提供的构建目录变量
  if(DEFINED FLUTTER_BUILD_DIR)
    set_target_properties(你的C++库目标名称 PROPERTIES
      RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FLUTTER_BUILD_DIR}/runner/Debug"
      RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FLUTTER_BUILD_DIR}/runner/Release"
    )
  endif()
endif()

二、用CMake POST_BUILD事件自动复制DLL

如果输出目录设置不生效,可以通过构建后命令强制将DLL复制到Flutter runner目录,自动区分Debug/Release:

if(WIN32)
  add_custom_command(TARGET 你的C++库目标名称 POST_BUILD
    # 复制当前构建的DLL到runner的对应配置目录
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
      $<TARGET_FILE:你的C++库目标名称>
      $<TARGET_FILE_DIR:${BINARY_NAME}>/$<CONFIG>/$<TARGET_FILE_NAME:你的C++库目标名称>
    # 可选:复制依赖的第三方DLL(如果你的库依赖其他DLL)
    COMMAND ${CMAKE_COMMAND} -E copy_directory
      $<TARGET_FILE_DIR:你的C++库目标名称>
      $<TARGET_FILE_DIR:${BINARY_NAME}>/$<CONFIG>
    COMMENT "Copying DLLs to Flutter runner directory"
  )
endif()

其中$<TARGET_FILE_DIR:${BINARY_NAME}>会自动解析为Flutter runner可执行文件的目录,$<CONFIG>会根据构建模式自动替换为Debug或Release,无需硬编码路径。

三、批处理脚本方案

如果CMake的配置仍有问题,可以写一个批处理脚本手动复制DLL,然后绑定到构建流程中:

  1. 创建windows/copy_dlls.bat脚本:
@echo off
:: 替换为你的C++库构建目录和Flutter runner目录
set "CPP_DEBUG_DIR=../your_cpp_lib/build/Debug"
set "CPP_RELEASE_DIR=../your_cpp_lib/build/Release"
set "FLUTTER_DEBUG_DIR=./runner/Debug"
set "FLUTTER_RELEASE_DIR=./runner/Release"

:: 复制Debug版本DLL
if exist "%CPP_DEBUG_DIR%\*.dll" (
  xcopy "%CPP_DEBUG_DIR%\*.dll" "%FLUTTER_DEBUG_DIR%\" /Y /Q
)

:: 复制Release版本DLL
if exist "%CPP_RELEASE_DIR%\*.dll" (
  xcopy "%CPP_RELEASE_DIR%\*.dll" "%FLUTTER_RELEASE_DIR%\" /Y /Q
)
  1. 在Flutter项目的pubspec.yaml中添加构建后钩子,自动执行脚本:
scripts:
  post-build-windows: "windows/copy_dlls.bat"

或者在CMake中添加自定义目标调用脚本:

if(WIN32)
  add_custom_target(copy_dlls ALL
    COMMAND cmd /C "${CMAKE_CURRENT_LIST_DIR}/copy_dlls.bat"
    DEPENDS 你的C++库目标名称
    COMMENT "Running DLL copy script"
  )
endif()

四、Dart代码中动态获取运行时目录

如果需要在Dart层面动态适配路径,可以通过dart:io的Platform类获取当前可执行文件的目录(即Flutter runner的目录),然后拼接DLL路径:

import 'dart:io';
import 'package:path/path.dart' as path;

void loadCppLib() {
  // 获取Flutter runner的运行时目录
  final runtimeDir = path.dirname(Platform.resolvedExecutable);
  // 拼接DLL路径
  final dllPath = path.join(runtimeDir, 'your_lib.dll');
  final dylib = DynamicLibrary.open(dllPath);
  // 后续调用FFI方法...
}

这种方式不管项目是直接运行还是作为包被引用,都能正确定位到DLL所在的runner目录。

内容的提问来源于stack exchange,提问作者itsLeatch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 16:20:22