kivy / pyjnius

Access Java classes from Python
https://pyjnius.readthedocs.org
MIT License
1.4k stars 255 forks source link

Varargs support isn't implemented properly #555

Closed mduczek closed 1 year ago

mduczek commented 4 years ago

In java:

Double[] doubles = {1.0, 2.0};
// <T> List<T> asList(T... a)
System.out.println(Arrays.asList(doubles));
// [1.0, 2.0]
System.out.println(Arrays.asList(1.0, 2.0));
// [1.0, 2.0]

With jnius:

Arrays = autoclass('java.util.Arrays')
Arrays.asList([1.0, 2.0]).toString()
// [[F@694f9431]
// ([[1.0, 2.0]] but should be [1.0, 2.0])

which is wrong

Additionally, varargs doesn't work with autoboxing: https://github.com/kivy/pyjnius/issues/509

I checked out JPype out and it's working there properly so switched to using JPype :)

cmacdonald commented 4 years ago

If you do:

double[] doublesPrim = {1.0, 2.0};
System.out.println(Arrays.asList(doublesPrim));

you get:

[[D@2b71fc7e]

as the type is List<double[]> instead of List.

See also: https://stackoverflow.com/a/2926653. As the conversion of autoboxed types vs primitives is subtle, I'm not sure that Jnius can entirely replicate the semantics.

Interestingly, Arrays.asList(1.0, 2.0) doesnt work:

>>> Arrays.asList(1.0, 2.0).toString()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "jnius/jnius_export_class.pxi", line 864, in jnius.JavaMethod.__call__
  File "jnius/jnius_export_class.pxi", line 1036, in jnius.JavaMethod.call_staticmethod
  File "jnius/jnius_jvm_dlopen.pxi", line 91, in jnius.create_jnienv
jnius.JavaException: JVM exception occurred: class [F cannot be cast to class [Ljava.lang.Object; ([F and [Ljava.lang.Object; are in module java.base of loader 'bootstrap') java.lang.ClassCastException

which I would have expected to work. So there might be more need for autoboxing.

I think populate_args() needs to know if its dealing with a varargs.

cmacdonald commented 4 years ago

@hx2A as the most recent amazing varargs expert, could you add a few cents here?

Given that Java has differing varargs behaviour between double[] and Double[] we need to think carefully about what the correct resolution should be.

hx2A commented 4 years ago

I tried debugging the code and I don't see what to do here. The signature of the asList method is public static <T> List<T> asList(T... a), and the internal variable for that, definition_args, is [Ljava/lang/Object;. This problem is complicated by the fact that this is a generic method. It doesn't seem to have a way to figure out what subclass of Java Object it could convert a number to.

I do see that this works fine:

    Double = autoclass('java.lang.Double')
    Arrays.asList(Double(1.0), Double(2.0)).toString()

This might have less to do with varargs and more to do with the ambiguity of a generic function.

Julian-O commented 1 year ago

Closing because there doesn't seem to be a path to resolving this.