发布时间:2020年12月30日 - 5分钟阅读
从FlutterDesktop MacOS调用C库。
如何从FlutterDesktop(MacOS)调用c库?嗯....。
一体化的Flutter资源:flatteredwithflutter.com/flutterdesk…
FlutterDesktop和C
开始...
水平。中级
前提条件。安装软件包FFI
本文假设读者对FFI有所了解。如果没有,请检查这个。
我们将简要介绍
- 创建C库
- 在Flutter MacOS中集成C库
- 从Flutter MacOS呼叫
注:关于Dart FFI我们就不深入解释了,因为有专门的好文章。
FlutterDesktop和C
创建C库
每一件复杂的事情都是从一个基本的事情开始的。让我们创建一个简单的C库(Hello World)。
介绍CMake和makefile
创建一个c库涉及到一堆命令,你可以使用这些命令,也可以利用CMake。
FlutterDesktop和C | CMake
根据文件规定
CMake是一个可扩展的、开源的系统,它以一种独立于编译器的方式在操作系统中管理构建过程。
安装CMake的方法是
brew install cmake
CMake使用一个名为CMakeLists.txt的文本文件,在软件包的主目录下,指定设置软件所需的操作。用户通过移动到主目录并输入 cmake .CMake会进行配置过程,之后会在主目录下创建传统的Makefile。
cmake .
CMake会进行一个配置过程,之后会在主目录下创建一个传统的Makefile。然后通过输入
make
创建一个C头文件hello.h,其中有1个函数声明。
void hello_world();
让我们在hello.c中导入这个头文件吧
#include <stdio.h>
#include "hello.h" // OUR HEADER FILE
int main()
{
hello_world(); // FUNCTION FROM HEADER FILE
return 0;
}
void hello_world() // IMPLEMENTATION OF FUNCTION
{
printf("Hello World\n");
}
我们的文件夹结构是这样的
FlutterDesktop和C语言|文件夹结构|之前
最后,在CMakeLists.txt中,我们将命令定义为
cmake_minimum_required(VERSION 3.10)
project(first_c VERSION 1.0 LANGUAGES C)
add_library(first_c SHARED hello.c)
add_executable(hello_test hello.c)
set_target_properties(first_c PROPERTIES
PUBLIC_HEADER hello.h
VERSION ${PROJECT_VERSION}
SOVERSION 1
OUTPUT_NAME "hello"
)
-
cmake_minimum_required: 设置项目所需的CMake最小版本。
-
project: 为整个项目设置名称、版本和启用语言。 这里,我们使用first_c (我们的父文件夹名),版本为1.0,语言为C。
-
add_library:添加一个库到项目中。使用指定的源文件在项目中添加一个库。 我们的项目是first_c,我们指定从我们的hello.c程序中创建出Shared(动态库)。
-
add_executable: 使用指定的源文件在项目中添加一个可执行文件。 这将从我们的源文件(hello.c)中创建一个可执行文件(hello_test),我们可以测试我们生成的共享库。
-
set_target_properties: 目标可以拥有影响其构建方式的属性。
这里,我们的项目是first_c,属性写为
PROPERTIES prop1 value1
现在运行以下命令
cmake .
make
你会看到我们现在的文件夹结构为。
FlutterDesktop和C | 文件夹结构 | 后期工作
万岁,我们现在有了libhello.dylib!
在Flutter MacOS中集成C库
现在我们需要将C库集成到我们的Flutter桌面应用程序中。
所需的步骤在这个链接中都有记载,请跟着文章或上面的视频一起看。
- 在Xcode中打开
yourapp/macos/Runner.xcworkspace。 - 将您的预编译库(
libyourlibrary.dylib)拖入Runner/Frameworks。 - 单击
Runner并转到Build Phases选项卡。
- 将
libyourlibrary.dylib拖入Copy Bundle Resources列表。 - 在
Bundle Framework下,选中Code Sign on Copy。 - 在,
Link Binary With Libraries下,将状态设置为Optional。
- 单击
Runner并进入General选项卡。
- 将
libyourlibrary.dylib拖入Frameworks, Libararies and Embedded Content列表。 - 选择
Embed & Sign。
你的Flutter Desktop项目结构应该是这样的
FlutterDesktop and C | 文件夹结构 | Flutter
从Flutter MacOS呼叫
现在我们将从Flutter Desktop调用我们的动态库。
- 导入dart ffi包(存在于Flutter内部)为
import 'dart:ffi' as ffi
这有一个类DynamicLibrary。我们调用方法打开并加载我们的动态库(libhello.dylib)。
- 使用lookup或lookupFunction从加载的动态库中查找符号。
- 最后,调用函数'hello_world'(从头文件.h中暴露)
typedef hello_world_func = ffi.Void Function();
void openFromFlutter() {
final sysLib = ffi.DynamicLibrary.open('libhello.dylib');
final HelloWorld hello = sysLib
.lookup<ffi.NativeFunction<hello_world_func>>('hello_world')
.asFunction();
hello(); // Call the function
}
额外的
假设我们在C语言头文件中有一个函数,比如说
char *sayHello(char *str);
由于这接受输入参数和返回类型为char指针,我们需要将我们的Flutter字符串转换为/从Pointer。
- 我们指定了SystemCHello和SystemDartHello函数,它们基本上就是
typedef SystemCHello = ffi.Pointer<Utf8> Function(ffi.Pointer<Utf8> str);
typedef SystemDartHello = ffi.Pointer<Utf8>Function(ffi.Pointer<Utf8> str);
- 将我们的Flutter字符串转换为Utf8,并将其传递给函数。
final sysLib = ffi.DynamicLibrary.open('libfetchtemp.dylib');
final helloFromC = sysLib.lookupFunction<SystemCHello, SystemDartHello>('sayHello');
// Pass input
final name = Utf8.toUtf8(input);
// Call the function
final res = helloFromC(name);
- 由于从函数返回的值,也是一个指针,我们将其转换为Flutter String。
// Convert response into string
final strRes = Utf8.fromUtf8(res);
与Flutter相关的有趣文章在这里。
通过www.DeepL.com/Translator (免费版)翻译