android.netxamarin.androidxamarinjava-binding

Mono for Android Binding - Jagged array


We are binding a Java library that has a method like this:

void onDataReceived(java.lang.String fromNode, java.lang.String fromChannel, java.lang.String payloadType, byte[][] payload)

Notice the byte[][] payload parameter.

Everything compiles fine, except at runtime when the listener is fired from Java, we get the error:

System.NotSupportedException: Rectangular arrays are not currently supported.

Is this currently supported in Mono for Android binding projects?

Is there a different type we could use instead of byte[][] to get the job done?


Solution

  • Is this currently supported in Mono for Android binding projects?

    No. Guess I should fix that...

    Do you need the payload parameter? If you don't, you could just edit the generated code[^1] to remove the marshaling of payload.

    If you do need the payload parameter, you can edit the generated code and replace this:

    byte[][] payload = (byte[][]) JNIEnv.GetArray (native_payload, JniHandleOwnership.DoNotTransfer, typeof (byte[]));
    

    with this:

    byte[][] payload = JNIEnv.GetArray<byte[]> (native_payload);
    

    (At least, that change works for my trivial test [^2].)

    [^1]: Ew, editing generated code.

    [^2]: Trivial test:

    Action<byte[][], byte[][]> equal = (a, b) => {
            if (!a.SelectMany (_ => _).SequenceEqual (b.SelectMany (_ => _)))
                throw new InvalidOperationException ("Sequences don't match!\n" +
                        "Expected: " + string.Join (" ", a.SelectMany (_ => _).Select (_ => _.ToString ("x2"))) +
                        "  Actual: " + string.Join (" ", b.SelectMany (_ => _).Select (_ => _.ToString ("x2"))));
    };
    byte[][] data = new byte[][]{
        new byte[]{11, 12, 13},
        new byte[]{21, 22, 23},
        new byte[]{31, 32, 33},
    };
    using (var byteArrayArray = new Java.Lang.Object (JNIEnv.NewArray (data), JniHandleOwnership.TransferLocalRef)) {
        Console.WriteLine ("# jonp [[b: {0}", JNIEnv.GetClassNameFromInstance (byteArrayArray.Handle));
        byte[][] data2 = JNIEnv.GetArray<byte[]> (byteArrayArray.Handle);
        equal (data, data2);
    }