3

私はここでは初心者ですが、「大きな問題」があります

(Delphiの)DLLがあり、Javaでアクセスしたい。DLLの「本体」(.dpr)で単純なリターンまたはプロシージャを使用すると簡単です。しかし、デスクトップアプリケーションとWebアプリケーション(Javaを使用)で同じコードを使用したいので、インターフェイスを使用する必要があります。以下のコード:

TESTLIB.DLL

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

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の簡単なアプリケーションを使用してこれにアクセスする方法:

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など...例を提供できればより良いでしょう)

どうもありがとう!

4

2 に答える 2

3

一般に、Delphi DLL(stdcall呼び出し規約を使用)は、Win32APIにアクセスするのと同じ方法でアクセスされます。Delphi型のサイズを調べ、それらを同様のサイズのJava型に置き換えることで、適切な型マッピングを理解できるはずです。

PCHARJava文字列にマップされるため、提供される「インターフェース」は次のようになります。

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に提供されたバッファに書き込むだけの方が簡単です。

于 2013-03-25T18:30:42.040 に答える
2

デスクトップアプリケーションとWebアプリケーションで同じコードを使用したい(Javaを使用)

このタスクにJNI/JNAを使用する代わりに、Delphiコードは、直接のプロセス内通信方式ではなく、HTTP Webサービス(JSON / RESTなど)を介して公開できます。DelphiベースのWebサービスの場合、Indy、Synapseを使用するか、IIS用のISAPIDLLを構築できます。その後、JavaWebアプリケーションはWebサービスクライアントとして機能します。また、多くのオペレーティングシステムで実行できますが、JNI / JNAでは、両方の部分をコンパイルして同じターゲットで実行する必要がありました。


更新:コメントに関して、速度が非常に重要な場合は、共有メモリマップトファイルやIOCPなど、プロセス内通信の他のオプションがあります。これらは非常に高速です。

ただし、ソケットベースのソリューションが遅くなるとは思いません。DelphiアプリとJavaプロセスの間に直接ソケット接続を作成し、1秒あたり数千のメッセージを簡単に転送できます。メッセージが1ミリ秒以内に処理されない場合、問題が発生することはありますか?

Javaのドキュメントでは、プロセス間通信にパイプとソケットを使用することを提案しています。

プロセス間の通信を容易にするために、ほとんどのオペレーティングシステムは、パイプやソケットなどのプロセス間通信(IPC)リソースをサポートしています。IPCは、同じシステム上のプロセス間の通信だけでなく、異なるシステム上のプロセスにも使用されます。

于 2013-03-25T15:50:50.670 に答える