Skip to content

Commit

Permalink
changes from code review
Browse files Browse the repository at this point in the history
  • Loading branch information
craiglabenz committed Feb 14, 2024
1 parent 4b3a827 commit cdaccc5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 29 deletions.
47 changes: 27 additions & 20 deletions packages/mediapipe-core/lib/src/ffi_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extension NativeStrings on String {
///
/// See also:
/// * [toCharsPointerPointer]
Pointer<Char> toNative() => toNativeUtf8().cast<Char>();
Pointer<Char> copyToNative() => toNativeUtf8().cast<Char>();
}

/// Helpers to convert between a `List<String>` and a `Pointer<Pointer<Char>>`.
Expand All @@ -40,36 +40,39 @@ extension NativeListOfStrings on List<String> {
///
/// See also:
/// * [Pointer<Char>.toNative] for a non-list equivalent.
Pointer<Pointer<Char>> toNative() {
Pointer<Pointer<Char>> copyToNative() {
final ptrArray = calloc<Pointer<Char>>(length);
for (var i = 0; i < length; i++) {
ptrArray[i] = this[i].toNative();
ptrArray[i] = this[i].copyToNative();
}
return ptrArray;
}
}

/// Helpers to convert a [Pointer<Char>] into a [Uint8List].
extension DartAwareChars on Pointer<Char> {
/// Creates a Dart view on a pointer to utf8 chars in native memory, cast as
/// unsigned, 8-bit integers. This method does not copy the data out of native
/// memory.
/// Creates a Dart view on native memory, cast as unsigned, 8-bit integers.
/// This method does not copy the data out of native memory.
///
/// If this is called on a `nullptr`, the method returns `null`.
Uint8List? toUint8List(int length) {
if (isNullPointer) return null;
/// Throws an exception if the method is called on a `nullptr`.
Uint8List toUint8List(int length) {
if (isNullPointer) {
throw Exception('Unexpectedly called `toUint8List` on nullptr');
}
RangeError.checkNotNegative(length, 'length');
return cast<Uint8>().asTypedList(length);
}

/// Converts the C memory representation of a string into a Dart [String].
///
/// If this is called on a `nullptr`, the method returns `null`.
/// Throws an exception if the method is called on a `nullptr`.
///
/// See also:
/// * [toDartStrings]
String? toDartString({int? length}) {
if (isNullPointer) return null;
String toDartString({int? length}) {
if (isNullPointer) {
throw Exception('Unexpectedly called `toDartString` on nullptr');
}
return cast<Utf8>().toDartString(length: length);
}
}
Expand All @@ -80,12 +83,14 @@ extension DartAwarePointerChars on Pointer<Pointer<Char>> {
/// cast as a `List<String>`. This method does not copy the data out of native
/// memory.
///
/// If this is called on a `nullptr`, the method returns `null`.
/// Throws an exception if the method is called on a `nullptr`.
///
/// See also:
/// * [toDartString], for a non-list equivalent.
List<String?>? toDartStrings(int length) {
if (isNullPointer) return null;
List<String?> toDartStrings(int length) {
if (isNullPointer) {
throw Exception('Unexpectedly called `toDartStrings` on nullptr');
}
final dartStrings = <String?>[];
int counter = 0;
while (counter < length) {
Expand All @@ -101,9 +106,11 @@ extension DartAwareFloats on Pointer<Float> {
/// Creates a Dart view on a pointer to floats in native memory, cast as a
/// Float32List. This method does not copy the data out of native memory.
///
/// If this is called on a `nullptr`, the method returns `null`.
Float32List? toFloat32List(int length) {
if (isNullPointer) return null;
/// Throws an exception if the method is called on a `nullptr`.
Float32List toFloat32List(int length) {
if (isNullPointer) {
throw Exception('Unexpectedly called `toFloat32List` on nullptr');
}
RangeError.checkNotNegative(length, 'length');
return cast<Float>().asTypedList(length);
}
Expand All @@ -115,7 +122,7 @@ extension NativeFloats on Float32List {
/// Copies a [Float32List] into native memory as a `float*`.
///
/// Returns an [allocator]-allocated pointer to the result.
Pointer<Float> toNative({Allocator allocator = malloc}) {
Pointer<Float> copyToNative({Allocator allocator = malloc}) {
final Pointer<Float> result = allocator<Float>(length)
..asTypedList(length).setAll(0, this);
return result.cast();
Expand All @@ -128,7 +135,7 @@ extension NativeInts on Uint8List {
/// Copies a [Uint8List] into native memory as a `char*`.
///
/// Returns an [allocator]-allocated pointer to the result.
Pointer<Char> toNative({Allocator allocator = malloc}) {
Pointer<Char> copyToNative({Allocator allocator = malloc}) {
final Pointer<Uint8> result = allocator<Uint8>(length)
..asTypedList(length).setAll(0, this);
return result.cast();
Expand Down
18 changes: 9 additions & 9 deletions packages/mediapipe-core/test/ffi_utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,41 +55,41 @@ void main() {

group('Strings should', () {
test('be convertable to char*', () {
final Pointer<Char> abc = 'abc'.toNative();
final Pointer<Char> abc = 'abc'.copyToNative();
calloc.free(abc);
});

test('be round-trippable', () {
expect('abc'.toNative().toDartString(), 'abc');
expect('abc'.copyToNative().toDartString(), 'abc');
});
});

group('Lists of Strings should', () {
test('be convertable to char**', () {
final Pointer<Pointer<Char>> strings = ['abc'].toNative();
final Pointer<Pointer<Char>> strings = ['abc'].copyToNative();
calloc.free(strings);
});

test('be round-trippable', () {
expect(['abc'].toNative().toDartStrings(1), ['abc']);
expect(['abc'].copyToNative().toDartStrings(1), ['abc']);
});
});

group('Uint8List should', () {
test('be convertable to Pointer<Char>', () {
final Pointer<Char> ptr = Uint8List.fromList([1, 2, 3]).toNative();
final Pointer<Char> ptr = Uint8List.fromList([1, 2, 3]).copyToNative();
malloc.free(ptr);
});

test('be round-trippable', () {
expect(
Uint8List.fromList([1, 2, 3]).toNative().toUint8List(3).toList(),
Uint8List.fromList([1, 2, 3]).copyToNative().toUint8List(3).toList(),
<int>[1, 2, 3],
);
});

test('copy memory with toList', () {
final ptr = Uint8List.fromList([1, 2, 3]).toNative();
final ptr = Uint8List.fromList([1, 2, 3]).copyToNative();
final List<int> ints = ptr.toUint8List(3).toList();
calloc.free(ptr);
expect(ints[0], 1);
Expand All @@ -101,13 +101,13 @@ void main() {
group('Float32List should', () {
test('be convertable to Pointer<Char>', () {
final Pointer<Float> ptr =
Float32List.fromList([1.0, 2.0, 3.1]).toNative();
Float32List.fromList([1.0, 2.0, 3.1]).copyToNative();
malloc.free(ptr);
});

test('be round-trippable', () {
final doubles = Float32List.fromList([1.1, 2.2, 3.3])
.toNative()
.copyToNative()
.toFloat32List(3)
.toList();
expect(doubles[0], closeTo(1.1, 0.0001));
Expand Down

0 comments on commit cdaccc5

Please sign in to comment.