JuliaInterop / JavaCall.jl

Call Java from Julia
http://juliainterop.github.io/JavaCall.jl
Other
118 stars 53 forks source link

Invoking a method that modifies an input parameter #83

Open sorokod opened 5 years ago

sorokod commented 5 years ago

I am invoking a Java method that accepts an array as a parameter and returns an int, something like int method(byte[] out). method is modifying the out parameter which I would like to pick Julia side.

On Julia side I have:

jout = Array{UInt8}(undef, 64)
jcall(object, "method", jint, (Array{jbyte,1}), jout)

But what I see is that jout is not affected by the invocation. How do I implemented this invocation pattern with JavaCall?

dfdx commented 5 years ago

JavaCall automatically converts Julia arrays to Java arrays and vice versa, but they don't share memory. What you pass to the Java method is actually a copy, that's why the argument isn't modified.

If you can add custom class to JVM, then the easiest way to overcome it would be to change signature to take ArrayList or return modified array (although this will lead to double conversion - between Julia and Java arrays).

Another approach would be to wrap Java arrays into a special type (say, JavaArrray) that you can pass and extract explicitly. But it's quite a big piece of work since Java treats all the primitive and object arrays differently (e.g. you construct byte[] using NewByteArray, int[] using NewIntArray, Object[] using NewObjectArray, etc.; access to elements is also specific for each array type).

sorokod commented 5 years ago

Yes, an adapter can work, but an extra copy is a concern.

dfdx commented 5 years ago

If you have a lot of code already working with byte[], you can create a no-copy wrapper for it instead of ArrayList. Something like:

class ArrayWrapper {
    private byte[];
   // constructor and accessors
}