How can I call a Delphi function that returns a string using JNA?

前端 未结 2 1570
我在风中等你
我在风中等你 2020-12-20 21:33

I\'m working on calling functions from a Delphi compiled *.so file from a Java program. After some research it seems like JNA is he way to go. Before diving into some comple

相关标签:
2条回答
  • 2020-12-20 21:53

    Besides that, using stdcall on 64-bit Linux is not entirely logical either. It probably works, since there usually is only one calling convention on a 64-bit target, but correct, it isn't. Use cdecl;

    0 讨论(0)
  • 2020-12-20 22:06

    A Delphi or FreePascal string is a managed type that cannot be used as a JNA type. The JNA documentation explains that Java String is mapped to a pointer to a null-terminated array of 8 bit characters. In Delphi terms that is PAnsiChar.

    So you can change the input parameter in your Pascal code from string to PAnsiChar.

    The return value is more problematic. You will need to decide who allocates the memory. And whoever allocates it must also free it.

    If the native code is responsible for allocating it then you'd need to heap allocate the null-terminated string. And return a pointer to it. You'd also need to export a deallocator so that the Java code can ask the native code to deallocate the heap allocated block of memory.

    It is usually more convenient to allocate a buffer in the Java code. Then pass that to the native code and let it fill out the content of the buffer. This Stack Overflow question illustrates the technique, using the Windows API function GetWindowText as its example: How can I read the window title with JNI or JNA?

    An example of this using Pascal would be like so:

    function GetText(Text: PAnsiChar; Len: Integer): Integer; stdcall;
    const
      S: AnsiString = 'Some text value';
    begin
      Result := Length(S)+1;//include null-terminator
      if Len>0 then
        StrPLCopy(Text, S, Len-1);
    end;
    

    On the Java side, I guess the code would look like this, bearing in mind that I know absolutely nothing about Java.

    public interface MyLib extends StdCallLibrary {
        MyLib INSTANCE = (MyLib) Native.loadLibrary("MyLib", MyLib.class);
        int GetText(byte[] lpText, int len);
    }
    
    ....
    
    int len = User32.INSTANCE.GetText(null);
    byte[] arr = new byte[len];
    User32.INSTANCE.GetText(arr, len);
    String Text = Native.toString(arr);
    
    0 讨论(0)
提交回复
热议问题