首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNA与DLL (Delphi)

JNA与DLL (Delphi)
EN

Stack Overflow用户
提问于 2013-03-25 20:30:33
回答 2查看 2.2K关注 0票数 3

我是一个新来的(Bie),但是,我有一个“大问题”

我有一个DLL (在Delphi中),我想通过Java访问它。如果在DLL的“主体”(.dpr)中使用简单的返回或过程,就会很容易。但是我需要使用一个接口,因为我想在桌面应用程序和Web应用程序(使用java)中使用相同的代码。代码如下:

TESTLIB.DLL

代码语言:javascript
复制
library TESTLIB;  
{$DEFINE TESTLIB}  

uses  
  System.SysUtils,  
  System.Classes,  
  TestInt in 'TestInt.pas';  

{$R *.res}  

function MyReturn(Test: PTest): PChar; stdcall;  
begin  
    Result := 'Im Here!';  
    Test^.vResult := 'Test 123';  
end;  

exports MyReturn;  

begin  
end.

接口TestInt.pas

代码语言:javascript
复制
unit TestInt;  

interface  

type  
  PTest = ^TTest;  
  TTest = record  
    vResult: PChar;  
  end;  

  {$IFNDEF TESTELIB}  
  function MyReturn(Test: PTest): PChar; stdcall;  
  {$ENDIF}  

implementation  

{$IFNDEF TESTELIB}  
function MyReturn; external 'TESTLIB.DLL' name 'MyReturn';  
{$ENDIF}  

end.

以及我如何在Delphi中使用一个简单的应用程序来访问它:

代码语言:javascript
复制
unit FormMain;  

interface  

uses  
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,   Vcl.Graphics,  
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;  

type  
  TForm1 = class(TForm)  
    Button1: TButton;  
    procedure Button1Click(Sender: TObject);  
  private  
    { Private declarations }  
  public  
    { Public declarations }  
  end;  

var  
  Form1: TForm1;  

implementation  

{$R *.dfm}  

uses TestInt;  //The interface

procedure TForm1.Button1Click(Sender: TObject);  
var  
  Test: TTest; //Type declared in Interface TestInt.pas  
begin  
    ShowMessage(MyReturn(@Test)); //Returns Im Here!  

    ShowMessage(Test.vResult); //Test 123  
end;  

end.

我想使用Java (JNI、JNA等)访问它。如果能提供一个例子就更好了)

非常感谢各位!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-26 02:30:42

通常,访问Delphi (使用标准调用约定)的方式与访问Win32 API的方式相同。您应该能够通过检查Delphi类型的大小并将其替换为类似大小的Java类型来找出适当的类型映射。

PCHAR映射到一个Java字符串,因此您提供的“接口”将如下所示:

代码语言:javascript
复制
public interface TestInt extends StdCallLibrary {
    TestInt INSTANCE = (TestInt)Native.loadLibrary("TestInt", TestInt.class);

    class Test extends Structure {
        public String vResult;
        public Test() { }
        public Test(Pointer p) { 
            super(p);
            read();
        }
        protected List getFieldOrder() { return Arrays.asList(new String[] { "vResult" }); }
    }

    String MyReturn(Test test);
}

记住David关于返回字符串的警告;如果delphi分配内存,它必须稍后释放内存,因此让调用者(Java)传入分配的内存并让delphi简单地写入所提供的缓冲区通常更容易。

票数 3
EN

Stack Overflow用户

发布于 2013-03-25 23:50:51

希望在桌面应用程序和网络应用程序中使用相同的代码(使用java)

您的Delphi代码可以通过HTTP web服务(例如JSON/REST)公开,而不是使用直接的进程内通信方法,而不是使用JNI/JNA来完成此任务。对于基于Delphi的web服务,您可以使用Indy、Synapse或为IIS构建ISAPI DLL。然后,Java Web应用程序充当web服务客户端。它可以运行在多个操作系统上,而JNI/JNA要求这两个部分都编译并在同一目标上运行。

更新:关于您的评论,如果速度非常重要,还有其他进程内通信的选项,例如共享内存映射文件和IOCP,它们都非常快。

然而,我不认为基于套接字的解决方案会很慢。您可以在Delphi应用程序和Java进程之间创建直接套接字连接,并轻松地每秒传输数千条消息。消息处理时间不超过1毫秒,确定会有问题吗?

Java documentation建议使用管道和套接字进行进程间通信:

为了方便进程之间的通信,大多数操作系统都支持进程间通信资源,如管道和套接字。进程间通信不仅用于同一系统上的进程之间的通信,而且还用于不同系统上的进程之间的通信。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15615007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档