Передача массива из DLL Delphi в JNA

1

Я использую библиотеку Java JNA для вызова DLL Delphi, который я создал. Функция Delphi, которую я использую, возвращает тип, являющийся массивом PAnsiChar. Проблема, которую я получаю, заключается в том, что когда я пытаюсь вызвать эту функцию в Java, она дает мне java.lang.Error: Invalid memory access.

Мой код Delphi находится здесь:

function doTest(inputStatement: PAnsiChar): TDynamicAnsiCharArray; stdcall;
begin
  SetLength(result, 3);

  result[0] := 'Line 1';
  result[1] := 'Line 2';
  result[2] := 'Line 3';
end;

Мой код Java здесь:

public interface CLib extends StdCallLibrary {

    CLib INSTANCE = (CLib) Native.loadLibrary("DatabaseLibrary", CLib.class);
    public String[] doTest(String input);
}

public Main() {

    String[] dllOut = CLib.INSTANCE.doTest("Test?");
    for(int i = 0; i < dllOut.length; i++){
        System.out.println(dllOut[i]);
    }
}

Полная ошибка Java здесь:

Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invoke(Function.java:430)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.doTest(Unknown Source)
at Main.<init>(Main.java:17)
at Main.main(Main.java:25)

Строка 17 - это строка с определением String [].

У меня такое чувство, что он не будет работать таким образом, но я надеюсь, что на самом деле есть способ.

  • 0
    Вы не можете сделать это так. Вы не можете вернуть строки Delphi через границу взаимодействия. Вы также не можете вернуть динамические массивы. Вам нужно будет найти другой путь. Обычно это будет связано с выделением памяти вызывающим абонентом.
  • 0
    Возможно stackoverflow.com/q/10158582/80901 полезен, он использует класс JNA Pointer
Показать ещё 5 комментариев
Теги:
dll
arrays
jna

1 ответ

0
Лучший ответ

Вы не TDynamicAnsiCharArray нам, что такое TDynamicAnsiCharArray, но я полагаю, что это динамический массив PAnsiChar:

type
  TDynamicAnsiCharArray = array of PAnsiChar;

Это не допустимый тип для двоичного взаимодействия.

На стороне Java вы не можете использовать String[] в качестве возвращаемого значения по той же причине.

Есть много способов решить эту проблему. Ничего особенного. Я думаю, что, пожалуй, самое чистое - попросить функцию вернуть одну строку, содержащую весь список. Вы можете использовать что-то грубое, как строки с двойным нулевым символом. Или вы можете сериализовать список в массив JSON и вернуть этот текст. Для любого из этих вариантов вам просто нужно найти способ вернуть строку.

Самый чистый способ сделать это - предоставить вызывающему абоненту выделение памяти. Этот ответ охватывает эту технику: как я могу вызвать функцию Delphi, которая возвращает строку с помощью JNA?

Альтернативой тому, что вызывающий абонент выделяет память, является использование типа строки, выделенного из общей кучи. Очевидным выбором является тип COM BSTR, WideString в Delphi. Это представлено как WTypes.BSTR в JNA. Будьте осторожны, чтобы не использовать это как возвращаемое значение функции WideString хотя из-за того, что Delphi не следует за платформой ABI: почему WideString не может использоваться как возвращаемое значение функции для взаимодействия?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню