Возврат структуры из обратного вызова Java в C ++ - PullRequest
0 голосов
/ 26 сентября 2018

В своем программном приложении я использую нативную библиотеку на C ++ из Java с использованием JNA.Мне нужна функция обратного вызова, которая возвращает сложный объект Java в C ++.

Это может быть простой проблемой, но у меня нет опыта работы с C ++ или JNA, и я не могу успешно вернуть объект Java в C ++.

Большинство примеров, с которыми я сталкивался для функций обратного вызова JNA, просты, и они либо ничего не возвращают, либо возвращают простой нативный тип.

Мой нативный код выглядит следующим образом

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-код:

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");
}

Когда я запускаю приложение, вывод будет

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

вместо ожидаемого

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

Возможнопожалуйста, помогите мне понять, что я делаю не так?Ваша помощь очень ценится.

С уважением, H.

1 Ответ

0 голосов
/ 01 октября 2018

Каждая JNA Structure выделяет свою собственную память, которая может быть GC'd, как только она выходит из области видимости.

Вам необходимо либо передать свой нативный код памяти в код Java длябыть заполненным (вместо того, чтобы выделять и возвращать его), или сохранять строгую ссылку на каждые Structure, которая возвращается из кода Java для предотвращения GC.

Вы также можете попробовать вызватьStructure.write() незадолго до возвращения;обычно Java синхронизирует структуры автоматически, но при возврате структуры из функции обратного вызова может возникать ошибка.

...