我是新人(bie),但是,我有一个“大问题”
我有一个DLL(在Delphi中),我想通过Java访问它。如果在DLL的“body”(。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等等)来访问它...欢迎这样的例子!
非常感谢!
答案 0 :(得分:3)
一般来说,Delphi DLL(使用stdcall调用约定)的访问方式与访问Win32 API的方式相同。您应该能够通过检查Delphi类型的大小并用类似大小的Java类型替换它们来找出适当的类型映射。
PCHAR
映射到Java String,因此提供的“接口”看起来像这样:
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只是写入提供的缓冲区。
答案 1 :(得分:1)
希望在桌面应用程序和Web应用程序中使用相同的代码 (使用java)
您可以通过HTTP Web服务(例如JSON / REST)而不是直接进程内通信方法来公开您的Delphi代码,而不是使用JNI / JNA执行此任务。对于基于Delphi的Web服务,您可以使用Indy,Synapse或为IIS构建ISAPI DLL。然后,Java Web Application充当Web服务客户端。它可以在许多操作系统上运行,而JNI / JNA要求两个部分都在同一目标上编译和运行。
更新:关于您的评论,如果速度非常重要,那么进程内通信还有其他选项,例如共享内存映射文件和IOCP,它们非常快。
但是我不认为基于套接字的解决方案会变慢。您可以在Delphi应用程序和Java进程之间创建直接套接字连接,并轻松地每秒传输数千条消息。如果在不到一毫秒的时间内没有处理消息,你确定会出现问题吗?
Java documentation建议使用管道和套接字进行进程间通信:
促进流程,大多数操作系统之间的通信 支持进程间通信(IPC)资源,如管道和 插座。 IPC不仅用于进程之间的通信 相同的系统,但不同系统的过程。