简体   繁体   中英

Returning struct from java callback to c++

In my software application I am using a native library in C++ from Java using JNA. I need a callback function that returns a complex java object to C++.

This might be a simple problem, but I have no experience with C++ or JNA, and I am unable to successfully return the java object to C++.

Most examples I have come across for JNA callback functions are simple, and either they don't return anything or return a simple native type.

My native code looks like the following

typedef const char* SMC_String;
int doNativeProcessing(SMC_String identifier, SMC_String lastName, SMC_String firstName)

typedef struct SimpleStruct
{
  int myInt;
  SMC_String myString;
} SimpleStruct;

typedef SimpleStruct* (*GetSimpleStruct_Callback)(SMC_String identifier);
...

// function that gets called from Java
int doNativeProcessing(SMC_String identifier, SMC_String lastName, SMC_String firstName)
{
  cout << "In native function" << endl;
  ...do some processing...
  callMyCallback();
  return 0;
}

// function that calls the callback 
void callMyCallback()
{
  SimpleStruct *retSimpleStruct = GetSimpleStruct_Callback("id");
  cout << "returned int: " << retSimpleStruct->myInt << endl;
  cout << "returned string: " << retSimpleStruct->myString << endl;
}

Java code:

public class SimpleStruct extends Structure {
  public static class ByReference extends SimpleStruct implements Structure.ByReference
  {}

  public SimpleStruct() {
    super();
  }

  @Override
  protected List<String> getFieldOrder() {
    return Arrays.asList("myInt", "myString");
  }

  public int myInt;
  public String myString;
}
...
public class GetSimpleStructCB implements Callback {
    public SimpleStruct.ByReference callback(final String requestId) {
      System.out.println("In Java callback");

      final SimpleStruct.ByReference retVal = new SimpleStruct.ByReference();
      retVal.myInt = 25;
      retVal.myString = "Hello World!";
      return retVal;
    }
}

public static void main(String[] args) {
    nativeLibrary = (NativeLibrary) Native.loadLibrary("my_native_dll", NativeLibrary.class);
    nativeLibrary.doNativeProcessing("id", "Doe", "John");
}

When I run the application, the output is

In native function
In Java callback
returned int: 0  
returned string: <blank value>  

instead of the expected

In native function
In Java callback
returned int: 25  
returned string: Hello World!  

Could you please help me figure out what I am doing wrong? Your help is much appreciated.

Regards, H.

Each JNA Structure allocates its own memory, which may be GC'd as soon as it goes out of scope.

You need to either have your native code pass the memory to the Java code to be populated (rather than allocating one and returning it), or keep a strong reference to every Structure that is returned from the Java code to prevent GC.

You might also try calling Structure.write() just before return; normally Java synchs structures automatically, but there may be a bug doing so when returning a Structure from a callback.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM