Search code examples
javapointersjna

Java JNA u32t return value of Pointer (Memory)


I try to access a method of a C++ DLL using JNA.

The Definition is as follows:

u32t OpenPort(u8t valueA, char* valueB, u32t* handle);

I am not sure how to map u32t and how to get the returnValue using or Pointer or Memory maybe?

I made it like this:

int OpenPort(byte valueA, String valueB, IntByReference handle); //u32t OpenPort(u8t type, char* myString, u32t* handle);

and calling

        IntByReference handle = new IntByReference();            
        byte i = 0;
        int error = myClass.OpenPort(i, "my string", handle);
        System.out.println(error  + " - " + handle.getValue());

The result is "0 - 0".

The error "0" is fine, but the returnValue should not be 0. As this is a value I need to pass to other methods like:

int ClosePort(IntByReference handle); //u32t ClosePort(u32t handle);

if I then start:

error = myClass.ClosePort(handle);

The return error says that the port handle is not valid.

A sample c# code from the DLL maker is like this:

UInt32 handle;
UInt32 error;
error= OpenPort(0, "teststring", out handle);
xError = ClosePort(handle);

Solution

  • Welcome to StackOverflow.

    The Pointer is actually pointing to native memory where there is a 32-bit value. But mapping just to Pointer does not tell you what's at the pointed-to location.

    You should use the IntByReference class to model a *uint32_t or similar pointer to a 32-bit value. The method will return a pointer, but you can use the getValue() method to retrieve the actual value you want.

    Also I notice that you've used NativeLong for the return type, but it's explicitly specified as 32-bit, so you want to use an int. Only use NativeLong for a situation where long is defined as 32-bit or 64-bit depending on the operating system bitness.

    Note that Java does not have a concept for signed vs. unsigned integers. While the value will be a 32-bit int you will need to handle negative values in your own code by converting them to their unsigned counterparts.

    So your mapping should be:

    int MethodName(byte valueA, String valueB, IntByReference returnValue);
    

    Then call with:

    IntByReference returnValue = new IntByReference();
    MethodName(valueA, ValueB, returnValue);
    int theU32tValue = returnValue.getValue();