Я использую библиотеку 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 [].
У меня такое чувство, что он не будет работать таким образом, но я надеюсь, что на самом деле есть способ.
Вы не TDynamicAnsiCharArray
нам, что такое TDynamicAnsiCharArray
, но я полагаю, что это динамический массив PAnsiChar
:
type
TDynamicAnsiCharArray = array of PAnsiChar;
Это не допустимый тип для двоичного взаимодействия.
На стороне Java вы не можете использовать String[]
в качестве возвращаемого значения по той же причине.
Есть много способов решить эту проблему. Ничего особенного. Я думаю, что, пожалуй, самое чистое - попросить функцию вернуть одну строку, содержащую весь список. Вы можете использовать что-то грубое, как строки с двойным нулевым символом. Или вы можете сериализовать список в массив JSON и вернуть этот текст. Для любого из этих вариантов вам просто нужно найти способ вернуть строку.
Самый чистый способ сделать это - предоставить вызывающему абоненту выделение памяти. Этот ответ охватывает эту технику: как я могу вызвать функцию Delphi, которая возвращает строку с помощью JNA?
Альтернативой тому, что вызывающий абонент выделяет память, является использование типа строки, выделенного из общей кучи. Очевидным выбором является тип COM BSTR
, WideString
в Delphi. Это представлено как WTypes.BSTR
в JNA. Будьте осторожны, чтобы не использовать это как возвращаемое значение функции WideString
хотя из-за того, что Delphi не следует за платформой ABI: почему WideString не может использоваться как возвращаемое значение функции для взаимодействия?