I have a DLL written in Delphi 2007 that I can't, for various reason, convert to being compiled in XE6.
I have written a wee test app in XE6 that calls the DLL, and that's all fine, but I need to pass string data from the DLL to the exe, and I am using a PCHAR to do this. However, consuming the PCHAR in the XE6 exe is proving to be a bit of a pain.
I read somewhere that in D2007 a PCHAR is actually a PANSICHAR, so I tried using a PANSICHAR and I make a call to the DLL but it just returns an empty string!
I have tried various other types like PWIDECHAR, String, WideString, ShortString and PCHAR. PCHAR does return something that looks like a Wide String, but I am not sure if it actually is because it didn't cast when I tried it :-)
So I am wondering what I am doing wrong? Am I passing the wrong type from the D2007 DLL? Should I be doing the consumption of the data differently in XE6?
-- EDIT -- Ok, I didnt get any results based on Remy's idea, so I have included my code this time and I am sure the solution will be obvious to someone. I appreciate the help :-)
This is the code for the DLL which is written in D2007:
library mydll;
uses
SysUtils
type
TOnCommandProc = procedure(sMessage:PAnsiChar);
stdcall;
var
FOnCommandProc: TOnCommandProc = nil;
procedure SetOnCommandProc(CallbackProc: TOnCommandProc);
stdcall;
begin
FOnCommandProc := CallbackProc;
end;
procedure OnEventMessage(Data: String);
var
BuffSize: Integer;
sOut: string;
oData : PAnsiChar;
begin
sOut:=Data;
BuffSize:=SizeOf(Char)*(Length(sOut)+1);
getmem(oData, BuffSize);
FillChar(oData^,BuffSize,0);
if (Length(sOut)>0) then
begin
Move(sOut[1], PAnsiChar(oData)^, BuffSize);
FOnCommandProc(oData);
end;
end;
procedure TryTheEvent;
begin
OnEventMessage('Hello');
end;
exports
SetOnCommandProc name 'SetOnCommandProc',
TryTheEvent name 'TryTheEvent';
end.
This is the calling EXE code written in Delphi XE6:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TOnCommandProc = procedure(sMessage:PAnsiChar); stdcall;
procedure SetOnCommandProc(CallbackProc: TOnCommandProc; sMessage:PAnsiChar); stdcall; external 'mydll.dll';
procedure TryTheEvent; stdcall; external 'mydll.dll';
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
class procedure MyOnCommandProc(sMessage:PAnsiChar); stdcall; static;
procedure OnCommand(sMessage : PAnsiChar);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
TryTheEvent;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetOnCommandProc(@MyOnCommandProc,0);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SetOnCommandProc(nil,0);
end;
class procedure TForm1.MyOnCommandProc(sMessage:PAnsiChar); stdcall;
begin
TForm1(sMessage).OnCommand(sMessage);
end;
procedure TForm1.OnCommand(sMessage :PAnsiChar);
begin
showmessage(sMessage);
end;
end.
OnEventMessage
is needlessly complex. It can be simplybegin FOnCommandProc(PChar(Data)); end;
Your question is really east to answer but I cannot do so because it is closed because you would not supply code. – David Heffernan