Flutter高性能本地调用插件h3_ffi的使用

Flutter高性能本地调用插件h3_ffi的使用


Build & 测试 codecov 许可: Apache 2.0

H3 Ffi

在大多数情况下,你不应该直接使用此库,请改用 h3_darth3_flutter

H3 C库版本: 3.7.2

该包允许你在你的Dart VM应用程序中直接使用 H3库

该包通过 FFI 来实现,绑定是使用 ffigen 自动生成的。

// 获取指定三角形内的六边形。
final h3 = const H3FfiFactory().byPath('../h3.so');
final hexagons = h3.polyfill(
  resolution: 5,
  coordinates: [
    GeoCoord(20.4522, 54.7104),
    GeoCoord(37.6173, 55.7558),
    GeoCoord(39.7015, 47.2357),
  ],
);

大多数C语言的H3函数都可以在H3类中找到,你可以通过H3Factory获取。如果你找不到需要的方法,你可以直接调用C函数,虽然这会更复杂,因为你需要直接处理FFI(你需要担心分配和原生类型)。如果你想尝试,可以使用H3CFactory来获取H3C实例(导入’package:h3_ffi/internal.dart’)。

安装

在大多数情况下,你不应该直接使用此库,请改用 h3_darth3_flutter

如果你使用 h3_flutter,你不需要编译H3 C库,它将自动构建。

pubspec.yaml文件中添加h3_ffi包。

获取编译好的H3库,根据平台的不同,扩展名可能是.so.dll等。

  • 你可以运行scripts/build_h3.sh脚本,编译后的库将位于h3_ffi/c/h3lib/build/h3.so(或Windows下的h3.dll

  • 你可以自己使用仓库中c文件夹里的C代码进行编译。与原始Uber代码相比,它有少量修改,使其更兼容iOS和macOS版本的h3_flutter。每次测试启动时都会重新编译并使用这些代码,所以应该工作得很好。

  • 你可以编译原始Uber的代码,也应该能很好地工作,只需确保使用正确的版本 - https://github.com/uber/h3

将你的库放置在某个位置,并使用H3FfiFactory().byPath('path/to/library.dll')加载它:


对贡献者的说明

测试

要使测试正常工作,你需要执行scripts/prepare_tests.sh脚本。这个脚本会从C代码构建H3库。

该脚本在macOS、Linux和Windows(需要bash)上都能很好地工作。

将包升级为与新的Uber H3库兼容

祝你好运

你需要cmake工具,如果你使用macOS,可以使用以下命令安装:

brew install cmake # 安装cmake

克隆H3存储库并创建工作文件夹:

git clone https://github.com/uber/h3 tmp/h3_sources 
# git checkout ... - 检出你需要的提交,目前稳定版本在stable-3.x分支
mkdir tmp/h3_sources/build
cd tmp/h3_sources/build

生成h3api.h文件并复制到c/h3lib文件夹:

cmake ..
rm -rf ../../../c/h3lib // 重新创建文件夹以移除旧的H3文件
mkdir ../../../c/h3lib

cp src/h3lib/include/h3api.h ../../../c/h3lib

复制其他源文件(*.h 和 *.c)到文件夹中。

cd ..
cp src/h3lib/include/* ../../c/h3lib
cp src/h3lib/lib/* ../../c/h3lib

使用scripts/sync_h3lib.sh脚本将c/h3lib文件夹复制到ios和macos文件夹:

sh scripts/sync_h3lib.sh

如果你想要在iOS和macOS上运行示例,你需要使用XCode添加.h和.c文件。

你可能会遇到一些构建错误,在我的情况下,我只是遵循XCode的指示来解决它们。

用于创建C到Dart绑定的代码生成工具叫做ffigen

要运行它,你需要安装LLVM:

brew install llvm

更多关于Flutter高性能本地调用插件h3_ffi的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter高性能本地调用插件h3_ffi的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用高性能本地调用插件h3_ffi的示例代码。h3_ffi是一个用于在Flutter应用中调用H3(Hexagonal Hierarchical Geospatial Indexing)库的FFI(Foreign Function Interface)插件。H3库用于地理空间索引和层次化数据组织。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加h3_ffi插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  h3_ffi: ^x.y.z  # 替换为实际的版本号

然后运行flutter pub get来安装依赖。

2. 创建Dart绑定

由于h3_ffi是一个FFI插件,你需要创建一些Dart代码来绑定到C函数。通常情况下,插件作者已经提供了这些绑定,但为了演示,这里是一个简化的例子。

假设h3_ffi插件已经提供了基础的绑定,你可以直接使用它们。在lib目录下创建一个新的Dart文件,例如h3_service.dart,用于封装H3相关的功能:

import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:h3_ffi/h3_ffi.dart';

class H3Service {
  late DynamicLibrary _h3Lib;

  H3Service() {
    _h3Lib = DynamicLibrary.open("libh3.so"); // 对于不同平台,可能需要使用不同的库文件,如libh3.dylib(macOS)或h3.dll(Windows)

    // 绑定H3函数
    h3GeoToH3 = _h3Lib
        .lookup<NativeFunction<IntPtr Function(Double, Double, Int32)>>('geoToH3')
        .asFunction<Int32 Function(Double, Double, Int32)>();

    // 可以继续绑定其他需要的H3函数
  }

  // 示例:将经纬度转换为H3索引
  int geoToH3(double lat, double lon, int resolution) {
    return h3GeoToH3(lat, lon, resolution);
  }
}

注意:这里假设h3_ffi已经提供了h3GeoToH3等函数的签名,实际情况中你可能需要根据插件的文档进行调整。

3. 在Flutter应用中使用

现在,你可以在你的Flutter应用中使用H3Service类来调用H3库的功能。例如,在main.dart中:

import 'package:flutter/material.dart';
import 'h3_service.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('H3 FFI Demo'),
        ),
        body: Center(
          child: H3Demo(),
        ),
      ),
    );
  }
}

class H3Demo extends StatefulWidget {
  @override
  _H3DemoState createState() => _H3DemoState();
}

class _H3DemoState extends State<H3Demo> {
  String h3Index = '';

  void _convertGeoToH3() {
    final h3Service = H3Service();
    final lat = 37.7749; // 示例纬度
    final lon = -122.4194; // 示例经度
    final resolution = 8; // 示例分辨率

    final index = h3Service.geoToH3(lat, lon, resolution);
    setState(() {
      h3Index = 'H3 Index: $index';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text(h3Index),
        Button(
          onPressed: _convertGeoToH3,
          child: Text('Convert Geo to H3'),
        ),
      ],
    );
  }
}

注意事项

  1. 平台特定的库文件:确保你为每个目标平台(如Android、iOS、Linux、macOS、Windows)提供了正确的库文件,并在CMakeLists.txt或相应的构建脚本中正确配置。

  2. 错误处理:在实际应用中,添加适当的错误处理逻辑,例如检查返回值是否为空或处理可能的异常情况。

  3. 性能优化:对于性能敏感的应用,确保在需要时释放资源,并考虑使用Dart的Isolate来避免阻塞UI线程。

  4. 文档参考:详细阅读h3_ffi插件的官方文档和H3库的文档,以获取更多功能和最佳实践。

希望这个示例能帮你开始使用h3_ffi插件进行高性能本地调用。

回到顶部