使用JNA从Delphi进行的Java回调崩溃了VM

时间:2015-10-26 12:35:14

标签: java delphi jna

我正在尝试使用以下java代码使用JNA实现从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中删除回调,一切正常!谢谢你的帮助!

1 个答案:

答案 0 :(得分:4)

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

您还需要使用StdCallCallback而不是Callback