likes
comments
collection
share

Flutter项目集成C源代码文件

作者站长头像
站长
· 阅读数 2

创建插件

flutter create --platforms=android,ios --template=plugin native_add

添加C源代码文件到插件项目

在插件项目的ios/Classes文件夹里添加C源代码文件,如添加如下的native_add.c:

int native_add(int a, int b)
{
    return a + b;
}

配置iOS自动编译

用Xcode打开插件项目下的example/ios/Runner.xcworkspace,在Xcode里的Runner文件夹上右击,通过Add Files to "Runner"添加native_add.c文件。

配置Android自动编译

在插件项目的android文件夹里新建如下的CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)
add_library( native_add SHARED ../ios/Classes/native_add.cpp )

在同目录的build.gradle文件里添加如下的externalNativeBuild部分:

android {
  // ...
  externalNativeBuild {
    cmake {
      path "CMakeLists.txt"
    }
  }
  // ...
}

自动生成FFI绑定

添加头文件到插件项目,如添加如下的native_add.h到插件项目根目录:

int native_add(int a, int b);

添加ffigen到插件项目pubspec.yaml的dev_dependencies,再添加ffigen配置信息到pubspec.yaml:

ffigen:
  name: 'NativeAdd'
  llvm-path:
    - 'llvm路径'
  output: 'lib/generated_bindings.dart'
  headers:
    entry-points:
      - 'native_add.h'

运行dart run ffigen自动生成FFI绑定(如果发生错误,可以尝试先运行flutter clean)。

加载编译后的库

可以把插件项目的lib/native_add.dart替换成如下内容:

import 'dart:ffi';
import 'dart:io';
import 'package:native_add/generated_bindings.dart';

final nativeAdd = NativeAdd(Platform.isAndroid
    ? DynamicLibrary.open('libnative_add.so')
    : DynamicLibrary.process());

修复test文件夹下的测试文件,之后可以把example/lib/main.dart替换成如下内容:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Text('1 + 2 = ${nativeAdd.native_add(1, 2)}'),
        ),
      ),
    );
  }
}

运行一下查看是否能正常调用。

在Flutter项目里调用插件

添加插件的依赖:

dependencies:
 # ...
 native_add:
   path: 插件路径

调用插件功能:

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

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

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: Scaffold(
       appBar: AppBar(
         title: const Text('App'),
       ),
       body: Center(
         child: Text('1 + 2 = ${nativeAdd.native_add(1, 2)}'),
       ),
     ),
   );
 }
}