Java 使用 JNA 的 Delphi 回调导致 VM 崩溃

Java Callback from Delphi using JNA crashes VM

我正在尝试使用 JNA 使用以下 java 代码实现从 Delphi 到 Java 的简单回调:

package jnaapp;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Callback;
public class JnaAppTest {

public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary)
        Native.loadLibrary((Platform.isWindows() ? "helloDelphi" : "c"),
                           CLibrary.class);
      public interface eventCallback extends Callback {
          public void callback(int id);
      }                     
    boolean setCallback(eventCallback callback);
    boolean TestFunction(byte[] text, int length);

}




public static void main(String[] args) throws Exception{
    byte[] text = new byte[100];

    CLibrary.eventCallback callback = new CLibrary.eventCallback(){
        public void callback(int id){
            System.out.println("I was called with: "+id);
        }
    };

    System.out.println(CLibrary.INSTANCE.setCallback(callback));
    System.out.println(CLibrary.INSTANCE.TestFunction(text, 100));
    System.out.println(Native.toString(text));
}

}

对应的Delphi代码如下:

Library helloDelphi;
uses
SysUtils,
Classes;

{$R *.res}

type TCallback = procedure(val: Integer); stdcall;

var
  cb : TCallback;

function setCallback(callBack : TCallback) : WordBool; stdcall; export;
begin
  cb := callBack;
  Result := True; 
end;



function TestFunction(stringBuffer : PAnsiChar; bufferSize : integer) : WordBool; stdcall; export
var s : string;
begin
   s := 'Hello World 2';
   StrLCopy(stringBuffer, PAnsiChar(s), bufferSize-1);
   cb(bufferSize);
   Result := True;
end;



exports TestFunction;
exports setCallback;

begin

end.

当从 Delphi 调用回调时,这会使 VM 崩溃。如果我从 Testfunction 中删除回调,一切正常!感谢您的帮助!

Delphi 使用 stdcall 调用约定,因此您需要使用 StdCallLibrary,而不是 Library。错误的约定将导致崩溃,因为被调用函数将使用与调用代码不同的堆栈布局。

您还需要使用 StdCallCallback 而不是 Callback