I'm trying to use JNA to call native API in Scala. I don't know how to pass pointer of array of byte (byte**
).
The signature of native API follows:
// this function mallocs some array buffer and stores it to passed pointer value
int func(byte **output);
Then I tried to pass pointer like this:
class NativeLibrary extends Library {
def func(output: Array[Byte]) // doesn't work. thats' for byte*, not byte**
def func(output: Array[Array[Byte]]) // doesn't work. JNA doesn't support this type
def func(output: Memory) // works, but I don't know how to get inner array
}
Both don't seem to work, returning broken pointer value or raising SEGV.
How can I retrieve array from this native function?
Actual native function: https://github.com/VOICEVOX/voicevox_core/blob/0.13.0/core/src/core.h#L169
CodePudding user response:
The **
represents a pointer to a pointer to a byte (the beginning of the byte array of interest), so the correct implementation is a PointerByReference
:
def func(output: PointerByReference): Int
The value being returned is ultimately a Pointer
. Since 'Memory' is a subclass of Pointer
designed for Java-level allocation of memory. Since it's a subclass it appears to work, but is not the correct implementation.
PointerByReference.getValue()
returns the Pointer
pointed to, removing one level of indirection to get you to byte*
:
// val size = size of buffer that you are passing to the actual function
val pbr = new PointerByReference()
// allocates the array and returns pointer to it
val resultCode = NativeLibrary.INSTANCE.func(pbr)
// get the pointer to the actual data
val dataPointer = pbr.getValue()
// get the data as a byte array
val data = dataPointer.getByteArray(0, size)
// later to free the `byte*`
resultCode = voicevox_wav_free(dataPointer)