如何使用 dart:ffi 将 Uint8List 转换为 C 等效数据类型
How to convert Uint8List to C equivalent datatype using dart:ffi
我正在尝试将图像发送到我计划使用 dart:ffi 运行 的自定义 C++ 代码。我已经成功 运行 我发送两个整数并将其中的一些作为另一个整数获取的 hello world 问题。
现在我想将整个图像发送给它并在我的 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 是:
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
s,并使用 data.buffer.asUint32List()
获取它们。)
您想要 return 列表 bool
。 bool
不受支持,您必须传递一个列表,例如 Int8
,您已将值分别设置为 1 和 0。 (如果你的列表是有界的并且大小合理,你可以使用位图。例如,如果你知道它总是 32 位长,将这些位打包到 Uint32 中作为 32 个 1 和 0。)
return列表有几种策略,ffi
中的列表当然意味着 Pointer<something>
。
如果列表是有界的,你可以在 Dart 端分配它,用函数传递指针并让 C 函数填充值,也许 returning 它填充的数字的整数英寸
如果列表是无界的,您必须允许 C malloc
它,因为只有 C 函数知道它需要多少 space。您现在需要 return 2 个值:指针和长度。由于您只能 return 一个值,因此您需要执行一些操作,例如传入 Pointer<Int32>
并让 C 函数为其分配长度。
我正在尝试将图像发送到我计划使用 dart:ffi 运行 的自定义 C++ 代码。我已经成功 运行 我发送两个整数并将其中的一些作为另一个整数获取的 hello world 问题。
现在我想将整个图像发送给它并在我的 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 是:
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
s,并使用 data.buffer.asUint32List()
获取它们。)
您想要 return 列表 bool
。 bool
不受支持,您必须传递一个列表,例如 Int8
,您已将值分别设置为 1 和 0。 (如果你的列表是有界的并且大小合理,你可以使用位图。例如,如果你知道它总是 32 位长,将这些位打包到 Uint32 中作为 32 个 1 和 0。)
return列表有几种策略,ffi
中的列表当然意味着 Pointer<something>
。
如果列表是有界的,你可以在 Dart 端分配它,用函数传递指针并让 C 函数填充值,也许 returning 它填充的数字的整数英寸
如果列表是无界的,您必须允许 C malloc
它,因为只有 C 函数知道它需要多少 space。您现在需要 return 2 个值:指针和长度。由于您只能 return 一个值,因此您需要执行一些操作,例如传入 Pointer<Int32>
并让 C 函数为其分配长度。