[英]"Invalid memory access" when calling Delphi DLL from Java
我们有一个 DLL,写在 Delphi 中,被 Java 应用程序调用。 最初我们在使用 PChar 或 ShortString 时遇到问题,但我们将它们更改为 PAnsiChar,所有问题似乎都已解决。
但是,当我们开始将 DLL 部署到我们的客户端时,大约 50% 的安装会出现以下错误:memory 访问无效。
DLL 中的第一行是写入我们的日志文件,但这并没有发生,这表明 Delphi 和 Java 数据类型之间存在问题。 有没有人知道 Delphi 和 Java 数据类型可以很好地协同工作?
Delphi DLL 代码:
function HasCOMConnection(COMServerName: PAnsiChar): Boolean; stdcall;
begin
WriteLog('HasCOMConnection: DLL entered');
Result := HasConnection(COMServerName);
end;
exports
HasCOMConnection;
从 Java 呼叫:
private interface IPMOProcessLabResult extends com.sun.jna.Library {
boolean HasCOMConnection(String COMServerName);
}
private boolean canConnectToCOMServer() {
try {
IPMOProcessLabResult lib = (IPMOProcessLabResult) Native.loadLibrary(config.libraryName, IPMOProcessLabResult.class);
return lib.HasCOMConnection(config.comServerName);
}
catch (Exception ex) {
new AppendLog(new Date(), this.getClass() + "\t" + ex.getClass() + "\t" + "Exception while trying to connect to COMServer: " + ex.getMessage(), "debug");
return false;
}
}
根据Java JNA 文档,Java String
在传递给本机代码时转换为const char*
:
Java
String
执行与本机类型const char*
和const wchar_t*
(NUL 终止数组)相同的 function。 为了在调用本机 function 时使用正确的类型,我们必须引入某种注释来标识 javaString
应如何转换。 JavaString
通常会转换为char*
,因为这是字符串最常见的用法。 在 function 调用中,字符串会自动转换为以 NUL 结尾的char
数组。 如果方法签名返回String
(例如strdup
),则返回的char*
值会自动复制到String
中。
因此,按原样传递String
时,在 Delphi 端使用PAnsiChar
是正确的。
但是,Delphi 中的 Delphi 2009+ 字符串与 Java 字符串一样以 UTF-16 进行本地编码。 因此,在 Java 端使用WString
会更有效(或者至少没有数据丢失的风险):
WString
class 用于标识宽字符串。 Unicode 值直接从 Java char 数组复制到本机wchar_t
数组。
并在Delphi端使用PWideChar
进行匹配,eg:
function HasCOMConnection(COMServerName: PWideChar): Boolean; stdcall;
private interface IPMOProcessLabResult extends com.sun.jna.Library {
boolean HasCOMConnection(WString COMServerName);
}
话虽如此,您的代码还有另外两个问题。
根据相同的 JNA 文档,a Java boolean
映射到本机int
,而不是bool
,因此您的 Delphi 代码需要使用Integer
(或Int32
)或更好的LongBool
,例如:
function HasCOMConnection(COMServerName: PAnsiChar{or PWideChar}): LongBool; stdcall;
更重要的是,如果本机库使用stdcall
调用约定,则必须从com.sun.jna.win32.StdCallLibrary
扩展IPMOProcessLabResult
,例如:
private interface IPMOProcessLabResult extends com.sun.jna.StdCallLibrary
否则,如果您从com.sun.jna.Library
扩展,那么您需要在本机端使用cdecl
:
function HasCOMConnection(COMServerName: PAnsiChar{or PWideChar}): LongBool; cdecl;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.