Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
&引用;无效内存访问“;从Java调用Delphi DLL时_Java_Delphi_Dll - Fatal编程技术网

&引用;无效内存访问“;从Java调用Delphi DLL时

&引用;无效内存访问“;从Java调用Delphi DLL时,java,delphi,dll,Java,Delphi,Dll,我们有一个用Delphi编写的DLL,由Java应用程序调用。最初,我们在使用PChar或ShortString时遇到了问题,但我们将其改为PAnsiChar,所有问题似乎都得到了解决 然而,当我们开始将DLL部署到客户端时,大约50%的安装会出现以下错误:内存访问无效 DLL中的第一行是写入日志文件,但这并没有发生,这表明Delphi和Java数据类型之间存在问题。有没有人知道哪些Delphi和Java数据类型可以很好地协同工作 Delphi DLL代码: function HasCOMCon

我们有一个用Delphi编写的DLL,由Java应用程序调用。最初,我们在使用PChar或ShortString时遇到了问题,但我们将其改为PAnsiChar,所有问题似乎都得到了解决

然而,当我们开始将DLL部署到客户端时,大约50%的安装会出现以下错误:内存访问无效

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
字符串
将转换为
const char*

Java
String
s执行与本机类型
const char*
const wchar\u t*
相同的功能(NUL终止数组)。为了在调用本机函数时使用正确的类型,我们必须引入某种注释来确定java
String
应该如何转换Java
String
s通常转换为
char*
,因为这是字符串最常见的用法。
字符串在函数调用中自动转换为以NUL结尾的
char
数组。如果方法签名返回
String
strdup
),则返回的
char*
值将自动复制到
字符串中

因此,当按原样传递
字符串时,在Delphi端使用
PAnsiChar
是正确的

但是,Delphi 2009+中的Delphi字符串与Java字符串一样,本机编码为UTF-16。因此,在Java端使用
WString
会更有效(或者至少不会有数据丢失的风险):

WString
类用于标识宽字符串。Unicode值直接从Java字符数组复制到本机
wchar\t
数组

并在Delphi端使用
PWideChar
进行匹配,例如:

函数HasCOMConnection(COMServerName:PWideChar):布尔值;stdcall;
专用接口IPMOProcessLabResult扩展com.sun.jna.Library{
布尔HasCOMConnection(WString-COMServerName);
}

话虽如此,您的代码还有另外两个问题

根据相同的JNA文档,Java
boolean
映射到本机
int
,而不是
bool
,因此您的Delphi代码需要使用
Integer
(或
Int32
)或更好的
LongBool
,例如:

函数HasCOMConnection(COMServerName:PAnsiChar{or PWideChar}):LongBool;stdcall;
更重要的是,如果本机库使用
stdcall
调用约定,则必须从扩展
IPMOProcessLabResult
,例如:

专用接口IPMOProcessLabResult扩展com.sun.jna.StdCallLibrary
否则,如果从
com.sun.jna.Library
扩展,则需要在本机端使用
cdecl

函数HasCOMConnection(COMServerName:PAnsiChar{or PWideChar}):LongBool;cdecl;

您是否阅读了上一个问题和我的答案下面的评论?从中我可以看出,Java字符串和Delphi PAnsiChar不兼容!PAnsiChar是一个指向C风格的每字符一字节数组/字符串的指针据我所知,Java字符串使用16位字符,就像Delphi字符串一样。所以乍一看,在Delphi端使用Char和PChar。只有非常旧的Delphi版本使用8位字符。您使用哪种Delphi版本?(编辑您的问题以添加详细信息)。@fpiette他使用Delphi 10.4确保您的本机代码不会引发任何未经处理的异常。这不只是stdcall vs cdecl吗?另外,我怀疑它应该是Delphi端的
LongBool
,我会质疑
boolean
映射。我希望它在Delphi中映射到一个4字节的Windows布尔值,
LongBool
。@DavidHeffernan谢谢,已更新