1

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?

jonathanpeppers
  • 26,115
  • 21
  • 99
  • 182

1 Answers1

2

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);
}
jonp
  • 13,512
  • 5
  • 45
  • 60
  • We actually need `payload`, it is the data we are interested in. I'm OK to do something ugly, just need to get access to that `byte[][]`. I can send you the binding project via email or something. What is the best way to send it to you? (I entered a Xamarin support request too) – jonathanpeppers Jun 25 '13 at 21:01
  • FYI, it seems works fine in cases where we pass in a `byte[][]` to Java, just not when it is a listener and Java is passing a `byte[][]` to C#. – jonathanpeppers Jun 25 '13 at 22:06
  • Brief investigation suggests that I need to do a runtime fix. I'll try to get this done ASAP for a 4.7.11 alpha release and future 4.6.10 stable release. – jonp Jun 25 '13 at 23:58
  • Brief investigation without an actual test is worthless. I think I have a workaround; answer updated. I'm still working on an actual fix. – jonp Jun 26 '13 at 00:16
  • For others that come across this, @jonp got this fixed in 4.7.12. Shouldn't be a problem in the future. – jonathanpeppers Jul 01 '13 at 13:07