如何使用 dart:ffi 将 Uint8List 转换为 C 等效数据类型



我正在尝试将图像发送到我计划使用 dart:ffi 运行的自定义C++代码。我已经成功地运行了hello world问题,我发送了两个整数,并将它们中的一些作为另一个intiger。

现在我想向它发送一个完整的图像并在我的C++代码上处理它。我能够使用以下代码从CameraImage获取Uint8List

Future<ui.Image> convertCameraImageToUiImage(CameraImage image) async {
imglib.Image libImage = imglib.Image.fromBytes(
image.width,
image.height,
image.planes[0].bytes,
format: imglib.Format.bgra,
);
final c = Completer<ui.Image>();
ui.decodeImageFromPixels(
libImage.getBytes(),
image.width,
image.height,
ui.PixelFormat.rgba8888,
c.complete,
);
return c.future;

}

然后我把它转换成Uint8List

ByteData data = await image.toByteData();
Uint8List bytes = data.buffer.asUint8List();

我的问题是,我应该如何定义查找函数以将Uint8List发送到C++代码并获取List<bool>,我的函数在 C++ 上期望cv::mat(我可以调整它以接收整数数组(作为参数并发送布尔向量。

这是我尝试过的

final List<bool> Function(Uint8List image) _imageToCode = nativeAddLib
.lookup<NativeFunction<List<bool> Function(List<Uint8List>)>>("imageToCode")
.asFunction();

问题是,bool 和 Uint8List 不是 C++ 支持的类型,因此函数无法识别它们。我应该如何通过通道发送它。

您必须将数据分配到一个Pointer<something>,然后将数据复制到 .然后,导出的 C 函数可以具有something*参数。您还需要传递数据的长度。由于目标是构造一个cv::Mat因此您可能希望传递几何图形,并从中推断数据长度。

因此,如果导出的 C 函数具有签名:

void process(int32_t width, int32_t height, uint8_t *bytes);

您的两个 Dart 类型定义将是:

typedef process_func = Void Function(Int32 width, Int32 height, Pointer<Uint8> bytes);
typedef ProcessFunc = void Function(int width, int height, Pointer<Uint8> bytes);

在查找中使用那些

_process = nativeLib
.lookup<NativeFunction<process_func>>('process')
.asFunction();

要分配缓冲区,请先import 'package:ffi/ffi.dart';并使用allocate

var outBuf = allocate<Uint8>(count: outSize);

然后使用 for 循环复制数据。或者,在outBuf上使用asTypedData以获取Uint8List并使用setAll

请记住在使用后free缓冲区。

(由于您的像素是 rgba8888,因此它们适合无符号的 32 位整数。您可能希望在指针中传递Uint32,并使用data.buffer.asUint32List()获取它们。

您要返回bool的列表。bool不支持,则必须传递一个列表,例如,将值分别设置为 1 和 0 的Int8。(如果列表有界且大小合理,则可以使用位图。例如,如果您知道它总是 32 位长,请将这些位打包到 Uint32 中,作为 32 个 1 和 0。

有几种返回列表的策略,其中ffi中的列表当然意味着Pointer<something>

如果列表是有界的,则可以在 Dart 端分配它,将指针与函数一起传递,并让 C 函数填充值,也许返回它填充的数字的整数。

如果列表是无界的,则必须允许 Cmalloc它,因为只有 C 函数知道它需要多少空间。现在需要返回 2 个值:指针和长度。由于您只能返回一个值,因此您需要执行诸如传入Pointer<Int32>之类的操作,并让 C 函数为其分配长度。

最新更新