Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native memory helpers #18

Closed
wants to merge 1 commit into from
Closed

Conversation

craiglabenz
Copy link
Collaborator

Adds helpers for converting between Dart and native memory for the following scenarios:

  1. A list of Dart doubles <-> A list of native floats
  2. A Dart Uint8List <-> A native Pointer<Char>.

Additionally, I would like to submit the function Uint8List toUint8List(Pointer<Char> val, {int? length}) for code review, even though it was committed previously.

--

The context for this PR is work around Embeddings, which are currently emitting random results on sequential runs, and for which I want to rule out these low level memory mapping helpers.

cc @Piinks

Copy link
Collaborator Author

@craiglabenz craiglabenz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider Uint8List toUint8List() as part of this code review, as well.

@dcharkes
Copy link
Member

dcharkes commented Feb 6, 2024

A Dart Uint8List <-> A native Pointer<Char>.

This is not entirely safe. The char type behaves as int8 on some platforms and as uint8 on other platforms. You can notice differences once using the indexed access operator in Dart for values 128-255 (or -128 to -1). Depending on the use case this might or might not be an issue. ByteBuffer and ByteData are classes that just passes around a piece of memory and does not promise a specific layout. The latter being able to pass around views with a non-zero offset. Again, it probably depends on the use case what solution makes sense.

We have a tracking issue for .asTypedList on Pointer<T extends AbiSpecificInteger>:

bool isNullOrNullPointer(Pointer? ptr) => ptr == null || ptr.isNullPointer;

/// Extension method for converting a [String] to a `Pointer<Utf8>`.
extension NativeFloats on List<double> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have a FloatList from dart:typed_data, and your FFI call is a leaf-call, you will not have to copy the list to native memory after dart-lang/sdk#44589. Can you structure your API around FloatList instead of List<Float>?


/// Converts a pointer to a (representing a list of) floats to a list of
/// Dart doubles.
List<double> toDartListDouble(Pointer<Float> floats, {int? length}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd return FloatList here. This would help with:

  1. If your users pass it in to anther FFI call you might not need to copy (see comment below).
  2. Indexed access is potentially not dynamic calls with the more specific types.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see Float32List and Float64List, but no agnostic FloatList. Is there a generic, adaptive FloatList somewhere?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, my bad. No, I meant to use Float32List.

@craiglabenz
Copy link
Collaborator Author

This is not entirely safe. The char type behaves as int8 on some platforms and as uint8 on other platforms.

A Dart Uint8List <-> A native Pointer<Char>.

This is not entirely safe. The char type behaves as int8 on some platforms and as uint8 on other platforms. You can notice differences once using the indexed access operator in Dart for values 128-255 (or -128 to -1). Depending on the use case this might or might not be an issue. ByteBuffer and ByteData are classes that just passes around a piece of memory and does not promise a specific layout. The latter being able to pass around views with a non-zero offset. Again, it probably depends on the use case what solution makes sense.

We have a tracking issue for .asTypedList on Pointer<T extends AbiSpecificInteger>:

Do you have any estimates on the tracking issue? It doesn't seem about to land, given that you haven't gotten any responses to your questions.

Absent that catch-all implementation, I'd love to quickly sync on the edge cases here to make sure I'm properly handling everything. Even with your helpful answer, I'm not sure how to exhaustively handle these edge cases.

@craiglabenz
Copy link
Collaborator Author

This PR is being replaced.

@craiglabenz craiglabenz deleted the native-memory-utils branch February 13, 2024 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants