Search code examples
javajna

JNA Issue - Only portions of an array populating from Java is used by DLL


I am newbie to Java and JNA. I am using JNA to load and use native DLL functions from Java.

I am facing a problem in passing a pointer to an array. As per the the spec, I am populating this array from Java and trying to send a pointer to this array to the DLL.

This is how the native call looks,

StartCom(UNUM8 *pCoPData)
From the spec: pCoPData -> Reference of the buffer holding the data

Correspoding JNA Mapping,

    int[] buf = new int[2];
    buf[0] = 0x1A;
    buf[1] = 0x10;

    Pointer pCoPData = new Memory(8);
    pCoPData.write(0, buf, 0, buf.length);

            Library.INSTANCE.StartCom(pCoPData);

When I execute the above code I notice from the dll log that only the first element of the array 0x1A is used and the second byte is ignored. The DLL always sees only the first element of the array.

I am assuming there could be only 2 possibilies for this issue could occur,

  1. The above approach I have taken to populate and send the address of a Java array  to the DLL is incorrect.
  2. The DLL is expecting a UNUM8* whereas I am sending a UNUM32*. I will try with byte[] instead of int[] and see if there is any difference.

Any suggestion is of great help ? Please let me know. Many thanks in advance !


Solution

  • Why would you expect proper results when you pass the function incorrect types on input?

    If the function is expecting a pointer to one or more 8-bit elements (byte in Java, presumably UNUM8 is 8 bits in your native code), then you need to pass the equivalent of a pointer to one or more 8-bit elements. You are passing a pointer to memory which you've initialized with two 32-bit elements. Here is what memory looks like in the 8-bit vs 32-bit case (all values represent 8-bit bytes):

    After writing two 8-bit values to memory:

    base+0x0: 0x1A
    base+0x1: 0x10
    

    After writing two 32-bit values to memory:

    base+0x0: 0x1A 0x00 0x00 0x00
    base+0x4: 0x10 0x00 0x00 0x00
    

    So you can see that if the native code starts reading from base, the values it sees are significantly different depending on how you initialize the memory.

    BTW, if the native code does not need to keep a reference to the memory you pass in longer than the function call itself, you can just use byte[] as the UNUM8* parameter, rather than allocating and initializing Memory.