Skip to content

How to convert JArray<jbyte> to Uint8List efficiently? #990

Closed

Description

@yanshouwang

When convert Uint8List to JArray, we can use the JArray<jbyte>.setRange extension method.
But I don't know how to do the opposite way.
Currently I can do this by use a for-loop, but I think this will spend a lot when convert a large byte array.

Activity

  1. dcharkes commented on Mar 12, 2024

    @dcharkes
    Collaborator

    Hi @yanshouwang!

    If the Struct containing the Array is created from a Pointer, you can use asTypedList on that pointer if you know the offset of the array in the struct.

    In general we should support something like what you're asking for. I've filed dart-lang/sdk#55170 to track that feature.

    Edit: wait, this is asking for JArray not Array!

    @HosseinYousefi over to you!

  2. mkustermann commented on Mar 12, 2024

    @mkustermann
    Member

    Right now we have JArray:

    class JArray<E> extends JObject { ... }
    extension ByteArray on JArray<jbyte> {
      int operator [](int index) {
        return elementAt(index, JniCallType.byteType).byte;
      }
    
      void operator []=(int index, int value) {
        RangeError.checkValidIndex(index, this);
        _allocate<JByteMarker>(sizeOf<JByteMarker>(), (ptr) {
          ptr.value = value;
          Jni.env.SetByteArrayRegion(reference.pointer, index, 1, ptr);
        });
      }
    
      void setRange(int start, int end, Iterable<int> iterable,
          [int skipCount = 0]) {
          ...
          Jni.env.SetByteArrayRegion(reference.pointer, start, size, ptr);
      }
    }

    Maybe this just needs a

    void getRange(int start, int end, Uint8List output) { ... }
    // or 
    Uint8List getRange(int start, int end) { ... }

    that is then implemented via Jni.env.GetByteArrayRegion to get C pointers to memory and then copy it to a dart typed list.

  3. HosseinYousefi commented on Mar 12, 2024

    @HosseinYousefi
    Contributor

    What @mkustermann said is possible. We can support the getRange operation as well.

    I first wrote something wrong about using JByteBuffers, that's not currently possible, because we can only convert direct JByteBuffers into Uint8Lists.


    If you don't have to use an array, you can use JByteBuffer directly, maybe that simplifies your code.

    final buffer = JByteBuffer.fromList(list);
    final list = buffer.asUint8List();
  4. yanshouwang commented on Mar 13, 2024

    @yanshouwang
    Author

    What @mkustermann said is possible. We can support the getRange operation as well.

    I first wrote something wrong about using JByteBuffers, that's not currently possible, because we can only convert direct JByteBuffers into Uint8Lists.

    If you don't have to use an array, you can use JByteBuffer directly, maybe that simplifies your code.

    final buffer = JByteBuffer.fromList(list);
    final list = buffer.asUint8List();

    The JByteArray is returned by a Kotlin method, so I can't use JByteBuffer instead, I think provide a getRange extension will be nice.

  5. moved this from Todo to In Progress in JNIgen trackeron Apr 18, 2024
  6. moved this from In Progress to Done in JNIgen trackeron Apr 24, 2024
  7. added a commit that references this issue on Apr 28, 2024
    880ca30
  8. added a commit that references this issue on May 2, 2024
    ed4628b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions