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
。
我正在尝试使用 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
。