I'm a new(bie) here but, I have a "big problem"
I Have a DLL (in Delphi) and I want to access it by Java. It's easy if you use a simple return or procedure in the "body" (.dpr) of DLL. But I need to use a Interface because I want to use a same code in a Desktop Application and a Web Application (using java). Code bellow:
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.
Interface 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.
and how I access this using a simple application in 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.
I want to access this using Java (JNI, JNA, etc... would be better if an example can be provided)
thanks a lot guys!
In general Delphi DLLs (using stdcall calling convention) are accessed in the same way that you would access Win32 APIs. You should be able to figure out appropriate type mappings by examining the sizes of the Delphi types and replacing them with similarly-sized Java types.
PCHAR
maps to a Java String, so your "interface" as provided would look something like this:
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);
}
Bear in mind David's warning about returning strings; if delphi allocates the memory, it must later free the memory, so it's usually easier to have the caller (Java) pass in allocated memory and have delphi simply write to the provided buffer.