[Flutter翻译]FlutterDesktop和C

426 阅读4分钟

原文地址:medium.com/flutter-com…

原文作者:medium.com/@aseemwango…

发布时间:2020年12月30日 - 5分钟阅读

从FlutterDesktop MacOS调用C库。

如何从FlutterDesktop(MacOS)调用c库?嗯....。

一体化的Flutter资源:flatteredwithflutter.com/flutterdesk…

www.youtube.com/watch?v=LUQ…

FlutterDesktop和C

开始...

水平。中级

前提条件。安装软件包FFI

本文假设读者对FFI有所了解。如果没有,请检查这个

我们将简要介绍

  1. 创建C库
  2. 在Flutter MacOS中集成C库
  3. 从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命令列表

  • 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桌面应用程序中。

所需的步骤在这个链接中都有记载,请跟着文章或上面的视频一起看。

  1. 在Xcode中打开yourapp/macos/Runner.xcworkspace
  2. 将您的预编译库(libyourlibrary.dylib)拖入Runner/Frameworks
  3. 单击 Runner 并转到 Build Phases 选项卡。
  • libyourlibrary.dylib 拖入 Copy Bundle Resources 列表。
  • Bundle Framework 下,选中 Code Sign on Copy
  • 在,Link Binary With Libraries 下,将状态设置为 Optional
  1. 单击 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相关的有趣文章在这里。

Flutter桌面应用的源码


通过www.DeepL.com/Translator (免费版)翻译