一个各平台调用 C/C++ 源码的例子,如何共享代码,配置相关的编译

官方的例子:https://docs.flutter.dev/development/platform-integration/c-interop

源码地址:https://github.com/gaoshang212/flutter_native_demo

创建一个插件

可以执行下面的命令来创建一个插件

flutter create --template=plugin --platforms=windows,macos,ios,android,linux flutter_native_demo

--platforms 可以指定支持哪些平台,如 windows,macos,ios,android,linux

如果没有创建相应平台目录,可以使用下面的命令开启相应的平台

flutter config --enable-linux-desktop  # 开启linux 桌面 flutter config --enable-macos-desktop  # 开启macos 桌面 flutter config --enable-ios # 开启ios  # 更多的命令可以通过help查看 flutter config --help

如果有字符串操作或转换,可以添加 ffi 的包:

flutter pub add ffi

项目结构

【Flutter】Flutter C/C++ 插件的开发 (支持 windows、macos、ios、android )

添加 C/C++ 源码文件

很多时候我们各平台是会共用一套C/C++ 源码的,我们先创建一个源码,就按官网的来,但我们创建在一个公共目录(官网创建在IOS/Classes下面)

libs/native_add/native_add.cpp

#include <stdint.h>  #ifdef WIN32 #define DART_API extern "C" __declspec(dllexport) #else #define DART_API extern "C" __attribute__((visibility("default"))) __attribute__((used)) #endif  DART_API int32_t native_add(int32_t x, int32_t y) {     return x + y; }

Dart

lib/flutter_native_demo.dart 中添加动态库的调用代码

final DynamicLibrary nativeAddLib = Platform.isMacOS || Platform.isIOS     ? DynamicLibrary.process()     : DynamicLibrary.open('libNativeAdd.${Platform.isWindows ? 'dll' : 'so'}');  final int Function(int x, int y) nativeAdd = nativeAddLib     .lookup<NativeFunction<Int32 Function(Int32, Int32)>>('native_add')     .asFunction();

我们改一下example/lib/main.dart 的代码

// 修改一下 platformVersion 的赋值 platformVersion = nativeAdd(1, 2).toString();

Windows 配置

libs/native_add 目录中添加一个 CMakeLists.txt ,用来编译 动态库。

cmake_minimum_required(VERSION 3.10)  # 项目名称 set(PROJECT_NAME "libNativeAdd") project(${PROJECT_NAME} LANGUAGES CXX)  # 源文件 add_library(${PROJECT_NAME} SHARED     "./native_add.cpp" )  # 动态库的输出目录 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<$<CONFIG:DEBUG>:Debug>$<$<CONFIG:RELEASE>:Release>") # 安装动态库的目标目录 set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") # 安装动态库,到执行目录 install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${PROJECT_NAME}.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime)

windows 目录下面的CMakeLists.txt 中添加相应的子目录

add_subdirectory("../libs/native_add" native_add)

example 目录下面执行下面的命令,来运行程序.

cd example flutter run -d windows -v

Android 配置

安卓的动态库,会自动添加lib头,我们改造一下libs/native_add/CMakeLists.txt 让他兼容windows和 android

cmake_minimum_required(VERSION 3.4)  # 项目名称 if (CMAKE_SYSTEM_NAME MATCHES "Windows")      set(PROJECT_NAME "libNativeAdd") else()     set(PROJECT_NAME "NativeAdd") endif()  project(${PROJECT_NAME} LANGUAGES CXX)  # 源文件 add_library(${PROJECT_NAME} SHARED     "./native_add.cpp" )  # Windows 需要把dll拷贝到bin目录 IF (WIN32)     # 动态库的输出目录     set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<$<CONFIG:DEBUG>:Debug>$<$<CONFIG:RELEASE>:Release>")     # 安装动态库的目标目录     set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")     # 安装动态库,到执行目录     install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${PROJECT_NAME}.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) ENDIF()

在 android/build.gradle 文件中添加 CMakeList.txt 路径

android { 	externalNativeBuild {         // Encapsulates your CMake build configurations.         cmake { 		        // 指定一个CMake 编译脚本的相对目录。             path "../libs/native_add/CMakeLists.txt"         }    } }

example 目录下面执行下面的命令,来运行程序

cd example flutter run -d <android> -v

说明:可以用flutter devices 查看支持设备,来替换

macOS 配置

macos/Classes 目录中执行下面的命令,给macOSlink 相关的代码

ln -s ../../libs/native_add/native_add.cpp ./

然后回到example 目录中执行

flutter run -d macos -v

说明:国内使用时会,通过CocoaPods 安装包会很慢,可以切换到清华的镜像。设置example 目录下macos 的 Podfile。

IOS 配置

IOS 和 macOS 的配置基本是一样的,注意一下目录就好了。

执行效果

【Flutter】Flutter C/C++ 插件的开发 (支持 windows、macos、ios、android )

【Flutter】Flutter C/C++ 插件的开发 (支持 windows、macos、ios、android )