Flutter Python集成插件python_ffi_dart的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter Python集成插件python_ffi_dart的使用

python_ffi_dart 是一个用于 Dart 的 Python 外部函数接口(FFI)。它允许您轻松地将任何纯 Python 模块导入到您的 Dart 或 Flutter 项目中。

使用入门

注意:此包旨在用于 Dart 控制台项目,对于 Flutter 应用程序,请参见 python_ffi 包。详细的使用说明可以在文档中找到。

示例项目

查看示例项目以获得一个工作的示例。

限制条件

在 Linux 和 Windows 上,此包期望系统上安装了 python3.11 并且可以在 PATH 中找到。Python 动态库不包含在包中,您必须通过指定 libPath 来使用本地副本调用 PythonFfiDart.instance.initialize()

完整示例 Demo

以下是一个完整的示例,展示如何在 Flutter 项目中使用 python_ffi_dart 插件与 Python 进行交互:

import "dart:typed_data";
import "package:collection/collection.dart";
import "package:python_ffi_dart/python_ffi_dart.dart";

// 定义类型映射条目类
typedef SendTyPythonCallback<T> = void Function({required T value});
typedef ReceiveFromPythonCallback<T> = T Function();

class TypeMappingEntry<T extends Object?> {
  const TypeMappingEntry({
    required this.pythonType,
    required this.value,
    this.dartType,
    this.sendToPython,
    this.receiveFromPython,
    this.equals,
  });

  final String? dartType;
  final String pythonType;
  final T value;
  final SendTyPythonCallback<T>? sendToPython;
  final ReceiveFromPythonCallback<T>? receiveFromPython;
  final bool Function(T, T)? equals;

  String get _dartType => dartType ?? T.toString();

  bool Function(T, T) get _equals => equals ?? (T a, T b) => a == b;

  void run() {
    try {
      print("\ntesting $_dartType ←→ $pythonType");
      final SendTyPythonCallback<T>? sendToPython = this.sendToPython;
      if (sendToPython == null) {
        print("├── dart -> python skipped ⚠️");
      } else {
        sendToPython(value: value);
        print("├── dart -> python successful ✅");
      }

      final ReceiveFromPythonCallback<T>? receiveFromPython =
          this.receiveFromPython;
      if (receiveFromPython == null) {
        print("└── python -> dart skipped ⚠️");
      } else {
        final T receivedValue = receiveFromPython();
        assert(
          _equals(receivedValue, value),
          "Python returned $receivedValue, but expected $value",
        );
        print("└── python -> dart successful ✅");
      }
    } on Exception catch (e) {
      print("└── ❌ error: $e");
    }
  }
}

Future<void> typeMappings() async {
  // 导入 Python 模块
  final type_mappings module = type_mappings.import();

  // 测试不同的数据类型映射
  TypeMappingEntry<Null>(
    dartType: "null",
    pythonType: "None",
    value: null,
    sendToPython: module.receive_none,
    receiveFromPython: module.request_none,
  ).run();

  TypeMappingEntry<bool>(
    dartType: "true",
    pythonType: "True",
    value: true,
    sendToPython: module.receive_bool_true,
    receiveFromPython: module.request_bool_true,
  ).run();

  TypeMappingEntry<bool>(
    dartType: "false",
    pythonType: "False",
    value: false,
    sendToPython: module.receive_bool_false,
    receiveFromPython: module.request_bool_false,
  ).run();

  TypeMappingEntry<int>(
    pythonType: "int",
    value: 42,
    sendToPython: module.receive_int,
    receiveFromPython: module.request_int,
  ).run();

  TypeMappingEntry<double>(
    pythonType: "float",
    value: 3.14,
    sendToPython: module.receive_float,
    receiveFromPython: module.request_float,
  ).run();

  TypeMappingEntry<String>(
    pythonType: "str",
    value: "Hello World",
    sendToPython: module.receive_str,
    receiveFromPython: module.request_str,
  ).run();

  TypeMappingEntry<Uint8List>(
    pythonType: "bytes",
    value: Uint8List.fromList("Hello World".codeUnits),
    sendToPython: module.receive_bytes,
    receiveFromPython: module.request_bytes,
  ).run();

  TypeMappingEntry<Map<String, int>>(
    pythonType: "dict[str, int]",
    value: const <String, int>{"one": 1, "two": 2, "three": 3},
    sendToPython: module.receive_dict,
    receiveFromPython: module.request_dict,
    equals: const MapEquality<String, int>().equals,
  ).run();

  TypeMappingEntry<List<int>>(
    pythonType: "list[int]",
    value: const <int>[1, 2, 3],
    sendToPython: module.receive_list,
    receiveFromPython: module.request_list,
    equals: (List<int> a, List<int> b) =>
        const ListEquality<int>().equals(a, b),
  ).run();

  // 其他类型的测试可以类似地进行
}

void _expectEqTest(Object? a, Object? b, {required bool expected}) {
  try {
    print("\ntesting $a == $b, expecting $expected");
    final bool result = a == b;
    if (result == expected) {
      print("└── successful ✅");
    } else {
      print("└── ❌ failed");
    }
  } on Exception catch (e) {
    print("└── ❌ error: $e");
  }
}

Future<void> eqTest() async {
  // 类型相等性测试逻辑
}

更多关于Flutter Python集成插件python_ffi_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Python集成插件python_ffi_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中集成并使用python_ffi_dart插件的示例代码案例。python_ffi_dart是一个允许Flutter通过FFI(外部函数接口)调用Python代码的插件。

1. 设置Flutter项目

首先,确保你已经创建了一个Flutter项目。如果还没有,可以使用以下命令创建:

flutter create my_flutter_app
cd my_flutter_app

2. 添加python_ffi_dart依赖

pubspec.yaml文件中添加python_ffi_dart依赖:

dependencies:
  flutter:
    sdk: flutter
  python_ffi_dart: ^最新版本号 # 请替换为当前最新版本号

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

3. 配置原生代码(iOS和Android)

iOS配置

对于iOS,你需要确保在ios/Runner/Info.plist中添加必要的权限配置,例如网络权限(如果你的Python脚本需要访问网络)。

Android配置

对于Android,通常不需要特别的配置,除非你的Python脚本需要访问特定的系统资源。

4. 编写Python脚本

在你的Flutter项目根目录下创建一个python_scripts文件夹,并在其中编写一个简单的Python脚本,例如hello.py

# hello.py
def greet(name):
    return f"Hello, {name}!"

5. 编写Flutter代码

lib目录下创建一个新的Dart文件,例如main.dart,并编写以下代码来加载和执行Python脚本:

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

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late PythonInterpreter interpreter;
  String? result;

  @override
  void initState() {
    super.initState();
    // 初始化Python解释器
    interpreter = PythonInterpreter(
      // 这里指定你的Python解释器路径(在开发时可以是本地路径,发布时需要调整)
      executablePath: 'path/to/your/python/executable', // 例如 '/usr/bin/python3' 或 'C:\\Python39\\python.exe'
    );

    // 加载并执行Python脚本
    interpreter.loadFile('path/to/your/python_scripts/hello.py').then((_) {
      interpreter.callFunction('greet', ['World']).then((response) {
        setState(() {
          result = response as String;
        });
      }).catchError((error) {
        print('Error calling Python function: $error');
      });
    }).catchError((error) {
      print('Error loading Python script: $error');
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Python FFI Example'),
        ),
        body: Center(
          child: Text(result ?? 'Loading...'),
        ),
      ),
    );
  }

  @override
  void dispose() {
    interpreter.dispose(); // 释放Python解释器资源
    super.dispose();
  }
}

6. 运行Flutter应用

确保你的Python解释器路径和Python脚本路径正确无误,然后运行Flutter应用:

flutter run

注意事项

  1. Python解释器路径:在开发环境中,你可以使用本地的Python解释器路径。但在发布时,你可能需要将Python解释器及其依赖打包进你的应用中。
  2. 跨平台差异:不同平台的Python解释器路径可能不同,确保为iOS和Android分别配置正确的路径。
  3. 权限问题:确保应用具有访问Python解释器和脚本文件的权限。

这个示例展示了如何使用python_ffi_dart插件在Flutter应用中调用Python代码。根据你的具体需求,你可能需要调整Python脚本和Dart代码。

回到顶部