flutter 和 c的那些交互传参

首先官方文章有介绍基本的使用方法:官方文档

基本使用

参考文章:在 flutter 上使用 c 代码 - (一) 有源码的项目_SimpleCoder's Blog-CSDN博客_flutter 调用c代码 

1、在vscode中使用指令新建一个plugin项目:flutter create -t plugin native_add
2、在新建的native_add项目中,新建native_add.cpp文件,并放到ios/Classes/,如下图

3、native_add.cpp添加两个方法

#include <stdint.h>

extern "C" {
// __attribute__((visibility("default"))) __attribute__((used))
int32_t native_add(int32_t x, int32_t y) { return x + y; }

double double_add(double x, double y) { return x + y; }
}

4、在andriod目录下,新建CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)  # for example

add_library( native_add

    # Sets the library as a shared library.
    SHARED

    # Provides a relative path to your source file(s).
    ../ios/Classes/native_add.cpp )

5、android/build.gradle文件

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


6、在lib/native_add.dart下添加内容

import 'dart:async';

import 'package:flutter/services.dart';

import 'dart:ffi'; // For FFI
import 'dart:io'; // For Platform.isX

final DynamicLibrary nativeAddLib = Platform.isAndroid
    ? DynamicLibrary.open("libnative_add.so")
    : DynamicLibrary.process();

final int Function(int x, int y) nativeAdd =
  nativeAddLib
    .lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add")
    .asFunction();

class NativeAdd {
  static const MethodChannel _channel =
      const MethodChannel('native_add');

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
}


7、在example/lib/main.dart中使用

8、在vscode的terminal窗口,使用cd example,进入native_add项目的example目录,并执行flutter run,测试是否能成功调用nativeAdd方法


9、测试结果:nativeAdd(1,2)等于3

以上就是简单的纯ffi官方的讲解介绍使用。但是在使用的过程中数据类型不仅仅是int和double,还有其他的一些问题是我遇到了并解决了的,这里给大家一些参考,希望能帮到你。

项目使用建议结合pub.dev上面的ffi和系统的ffi方法一起使用,

扩展以及遇到的问题及修复方案:

1. 我的c文件很多,并不是只有一个,而且c文件是已存在的,我只是创建一个交互逻辑使用它。

首先c文件还是按照之前的文件放置在ios/Classes/下面:

记得在CMakeLists.txt里面补充上所有的文件,注意如果是c的文件需要在公共引入方法那里导入头文件:文章参考《C++编程报错Error:Undefined reference to的常见解决办法》

extern “C”{

#include “OOXX.h”

}

注意格式换行要正确。

否则编译会出现异常:Undefined reference to ****

2. 传参类型有二级指针char **

官方demo讲述的只有int,doubel的基本类型,但是c里面也存在char * 和char **的参数类型,需要用什么dart的类型来桥接?(已通过代码验证有效,尤其是char **,有些文章说使用Pointer<Uint8>,我却使用dart怎么也转换不成对应的样子。

char *    使用Pointer<Utf8>来接。

char **   使用Pointer<Pointer<Utf8>>来接

使用示例(这里使用的toNativeUtf8(),是使用的pub库里面ffi:1.1.2里面的扩展):

3. allocate.dart文件,一些博友留一手不上传,这里我整理了一下不需要c币的一份连接:flutter和c调用allocation.dart文件-其它文档类资源-CSDN下载https://download.csdn.net/download/BUG_delete/76844837,这个可以在ffi:0.1.2版本中找到,或则我这里给你们贴出来代码:

// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:ffi';
import 'dart:io';

// Note that kernel32.dll is the correct name in both 32-bit and 64-bit.
final DynamicLibrary stdlib = Platform.isWindows
    ? DynamicLibrary.open("kernel32.dll")
    : DynamicLibrary.process();

typedef PosixMallocNative = Pointer Function(IntPtr);
typedef PosixMalloc = Pointer Function(int);
final PosixMalloc posixMalloc =
stdlib.lookupFunction<PosixMallocNative, PosixMalloc>("malloc");

typedef PosixFreeNative = Void Function(Pointer);
typedef PosixFree = void Function(Pointer);
final PosixFree posixFree =
stdlib.lookupFunction<PosixFreeNative, PosixFree>("free");

typedef WinGetProcessHeapFn = Pointer Function();
final WinGetProcessHeapFn winGetProcessHeap = stdlib
    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>("GetProcessHeap");
final Pointer processHeap = winGetProcessHeap();

typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
final WinHeapAlloc winHeapAlloc =
stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>("HeapAlloc");

typedef WinHeapFreeNative = Int32 Function(
    Pointer heap, Uint32 flags, Pointer memory);
typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
final WinHeapFree winHeapFree =
stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>("HeapFree");

/// Allocates memory on the native heap.
///
/// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
/// against the default public heap. Allocation of either element size or count
/// of 0 is undefined.
///
/// Throws an ArgumentError on failure to allocate.
Pointer<T> allocate<T extends NativeType>({int count = 1}) {
  final int totalSize = count * sizeOf<T>();
  Pointer<T> result;
  if (Platform.isWindows) {
    result = winHeapAlloc(processHeap, /*flags=*/ 0, totalSize).cast();
  } else {
    result = posixMalloc(totalSize).cast();
  }
  if (result.address == 0) {
    throw ArgumentError("Could not allocate $totalSize bytes.");
  }
  return result;
}

/// Releases memory on the native heap.
///
/// For POSIX-based systems, this uses free. On Windows, it uses HeapFree
/// against the default public heap. It may only be used against pointers
/// allocated in a manner equivalent to [allocate].
///
/// Throws an ArgumentError on failure to free.
///
// TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
// of testing the return integer to be non-zero.
void free(Pointer pointer) {
  if (Platform.isWindows) {
    if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
      throw ArgumentError("Could not free $pointer.");
    }
  } else {
    posixFree(pointer);
  }
}

使用:

Pointer<Uint8> soureData = allocate<Uint8>(count:source.length);

如果你使用的时候和我一样遇到allocate方法的第一行的sizeOf<T>();提示错误,不妨可以将这个类型提出来,在外部使用的地方乘好穿进去int值就好了:可以改成如下:

使用的地方: 

猜你喜欢

转载自blog.csdn.net/BUG_delete/article/details/122586171