[英]Call DLL written in Delphi from Java
I have a simple DLL written in Delphi 10.4.我有一个用 Delphi 10.4 编写的简单 DLL。 When I call the DLL from another Delphi application, everything works 100%, but when I call the same DLL from a Java application (using JNA) I get strange results.
When I call the DLL from another Delphi application, everything works 100%, but when I call the same DLL from a Java application (using JNA) I get strange results.
I initially declared my DLL input parameters of type PChar.我最初声明了 PChar 类型的 DLL 输入参数。 When I call the DLL from the Java app, I get funny characters inside my DLL.
当我从 Java 应用程序调用 DLL 时,我的 DLL 中出现了有趣的字符。 I changed it to ShortString, but then I loose the first character of the string in my DLL.
我将其更改为 ShortString,但随后我丢失了 DLL 中字符串的第一个字符。 I probably need to do some datatype casting in Java but I cannot find out what.
我可能需要在 Java 中进行一些数据类型转换,但我不知道是什么。 Can somebody perhaps help?
有人可以帮忙吗?
Here is a sample DLL in Delphi to demonstrate:这是 Delphi 中的示例 DLL 来演示:
procedure TestDataTypes(PCharVar: PChar; ShortStringVar: ShortString); stdcall;
begin
ShowMessage('PChar: ' + PCharVar + #13#10 +
'ShortString: ' + ShortStringVar);
end;
exports
TestDataTypes;
Code to call DLL from Delphi:从 Delphi 调用 DLL 的代码:
procedure TestDataTypes(PCharVar: PChar; ShortStringVar: ShortString); stdcall; external 'TestDataType.dll';
...
TestDataTypes(PChar('PChar Value'), 'ShortString Value');
Code to call DLL from Java:从 Java 调用 DLL 的代码:
INSTANCE.TestDataTypes("Java PChar Value", "Java ShortString Value");
Results: Top is when DLL is called from Delphi and bottom when it is called from Java:结果:顶部是从 Delphi 调用 DLL 时,底部是从 Java 调用时:
Some Feedback: I changed the datatype in Delphi to PAnsiChar and it works on my local pc.一些反馈:我将 Delphi 中的数据类型更改为 PAnsiChar,它可以在我的本地电脑上运行。 When deployed, it worked on some client machines but not others.
部署后,它可以在某些客户端机器上工作,但不能在其他机器上工作。 The error I get when I call the DLL from my Java app is "Invalid memory access".
当我从我的 Java 应用程序调用 DLL 时得到的错误是“无效的 memory 访问”。 I have added logging in my DLL and it seems it does not even enter the DLL.... I have also changed the Java datatype to WString but that did not make a difference.
我已经在我的 DLL 中添加了日志记录,它似乎甚至没有进入 DLL....
Delphi code: Delphi 代码:
function HasCOMConnection(COMServerName: PAnsiChar): Boolean; stdcall;
begin
WriteLog('HasCOMConnection: 64-Bit DLL entered');
Result := HasConnection(COMServerName);
end;
Java Call: 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;
}
}
PChar
is only an alias, which was changed to PWideChar
with Delphi 2009 (let's just say, standard string and character types were changed to Unicode
). PChar
只是一个别名,在 2009 年使用 Delphi 更改为PWideChar
(假设标准字符串和字符类型更改为Unicode
)。 So every character does now use 2 Bytes.所以现在每个字符都使用 2 个字节。
So in order to make your DLL working as it should, you should change PChar
to PAnsiChar
.因此,为了使您的 DLL 正常工作,您应该将
PChar
更改为PAnsiChar
。
Or you have to make some changes to your Java app so it does use some two-byte-character type.或者您必须对您的 Java 应用程序进行一些更改,以便它使用一些两字节字符类型。 But I have no Java experience, so I can't help you with that.
但是我没有 Java 的经验,所以我帮不了你。
And forget about shortstring, this type is not compatible to other languages!忘记短字符串,这种类型与其他语言不兼容!
See this site for more references about how to use and not to use DLLs.有关如何使用和不使用 DLL 的更多参考信息,请参阅此站点。
ShortString
is an old Delphi type that holds an ANSI string and stores the length in the first byte. ShortString
是一个旧的 Delphi 类型,它包含一个 ANSI 字符串并将长度存储在第一个字节中。 You shouldn't use it.你不应该使用它。
PChar
, in recent versions of Delphi, is an alias for PWideChar
. PChar
在最新版本的 Delphi 中是PWideChar
的别名。
You are using JNA to call native code from Java.您正在使用JNA从 Java 调用本机代码。
A Java String
internally uses UTF-16. Java
String
在内部使用 UTF-16。
JNA uses the following rules: JNA 使用以下规则:
String
is converted to PAnsiChar
String
转换为PAnsiChar
WString
is converted to PWideChar
WString
被转换为PWideChar
So, if you want to pass a Unicode string to the DLL, you should declare the Java method like this:因此,如果您想将 Unicode 字符串传递给 DLL,您应该像这样声明 Java 方法:
public void TestString(WString text);
And in Delphi:在 Delphi 中:
procedure TestString(Text: PChar); stdcall;
begin
ShowMessage(Text);
end;
And call the function like this:并像这样调用 function:
INSTANCE.TestString(new WString("A Unicode string"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.