繁体   English   中英

从 Java 调用 DLL 写在 Delphi

[英]Call DLL written in Delphi from Java

我有一个用 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.

我最初声明了 PChar 类型的 DLL 输入参数。 当我从 Java 应用程序调用 DLL 时,我的 DLL 中出现了有趣的字符。 我将其更改为 ShortString,但随后我丢失了 DLL 中字符串的第一个字符。 我可能需要在 Java 中进行一些数据类型转换,但我不知道是什么。 有人可以帮忙吗?

这是 Delphi 中的示例 DLL 来演示:

procedure TestDataTypes(PCharVar: PChar; ShortStringVar: ShortString); stdcall;
begin
  ShowMessage('PChar: ' + PCharVar + #13#10 +
              'ShortString: ' + ShortStringVar);
end;

exports
  TestDataTypes;

从 Delphi 调用 DLL 的代码:

procedure TestDataTypes(PCharVar: PChar; ShortStringVar: ShortString); stdcall; external 'TestDataType.dll';
...
TestDataTypes(PChar('PChar Value'), 'ShortString Value');

从 Java 调用 DLL 的代码:

INSTANCE.TestDataTypes("Java PChar Value", "Java ShortString Value");

结果:顶部是从 Delphi 调用 DLL 时,底部是从 Java 调用时: 在此处输入图像描述

一些反馈:我将 Delphi 中的数据类型更改为 PAnsiChar,它可以在我的本地电脑上运行。 部署后,它可以在某些客户端机器上工作,但不能在其他机器上工作。 当我从我的 Java 应用程序调用 DLL 时得到的错误是“无效的 memory 访问”。 我已经在我的 DLL 中添加了日志记录,它似乎甚至没有进入 DLL....

Delphi 代码:

function HasCOMConnection(COMServerName: PAnsiChar): Boolean; stdcall;
begin
  WriteLog('HasCOMConnection: 64-Bit DLL entered');
  Result := HasConnection(COMServerName);
end;

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只是一个别名,在 2009 年使用 Delphi 更改为PWideChar (假设标准字符串和字符类型更改为Unicode )。 所以现在每个字符都使用 2 个字节。

因此,为了使您的 DLL 正常工作,您应该将PChar更改为PAnsiChar
或者您必须对您的 Java 应用程序进行一些更改,以便它使用一些两字节字符类型。 但是我没有 Java 的经验,所以我帮不了你。

忘记短字符串,这种类型与其他语言不兼容!

有关如何使用和不使用 DLL 的更多参考信息,请参阅站点。

ShortString是一个旧的 Delphi 类型,它包含一个 ANSI 字符串并将长度存储在第一个字节中。 你不应该使用它。

PChar在最新版本的 Delphi 中是PWideChar的别名。

您正在使用JNA从 Java 调用本机代码。

Java String在内部使用 UTF-16。

JNA 使用以下规则:

  • String转换为PAnsiChar
  • WString被转换为PWideChar

因此,如果您想将 Unicode 字符串传递给 DLL,您应该像这样声明 Java 方法:

public void TestString(WString text);

在 Delphi 中:

procedure TestString(Text: PChar); stdcall;
begin
    ShowMessage(Text);
end;

并像这样调用 function:

INSTANCE.TestString(new WString("A Unicode string"));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM