Reputation: 2429
A friend asked me about writing a dll in C# for a delphi app. He wants to communicate with it using this function decleration:
function OpenAddOnFile(const mafCode: PWideChar; const mafFilePath: PWideChar;
const mafVersion: PWideChar): Pointer; stdcall;
The problem I have is translating it to C#. PWideChar isnt available etc... I've tried it like that:
public Pointer OpenAddOnFile(
[MarshalAs(UnmanagedType.LPWStr)]string mafcode,
[MarshalAs(UnmanagedType.LPWStr)]string maffilepath,
[MarshalAs(UnmanagedType.LPWStr)]string mafversion
)
But its not working for now :)
Further more how can I return a Pointer to my form in C#?
Can someone help me please? Thanks in advance!
Edit:\
He gave me this additional code: I asked him for the function call, he gave me this info:
unit unAddOn;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.ComCtrls;
function LoadAddOnFile(aPath: String; aVersion: String; var aFilePath: String;
var aCode: String): Boolean;
const
AddOnExt: String = '.maf';
implementation
function LoadAddOnFile(aPath: String; aVersion: String; var aFilePath: String;
var aCode: String): Boolean;
type
TOpenAddOnFile = function(const mafCode: PWideChar; const mafFilePath: PWideChar;
const mafVersion: PWideChar): Pointer; stdcall;
TCloseAddOnFile = procedure(var mafCode: PWideChar; var mafFilePath: PWideChar;
var mafQuitPopUp: PWideChar); stdcall;
var
CloseAddOnFile: TCloseAddOnFile;
OpenAddOnFile: TOpenAddOnFile;
AddOnMainForm: TForm;
AddOnHandle: THandle;
mafQuitPopUp: PWideChar;
mafFilePath: PWideChar;
mafVersion: PWideChar;
mafCode: PWideChar;
begin
Result := True;
mafQuitPopUp := PWideChar(EmptyStr);
mafFilePath := PWideChar(aFilePath);
mafCode := PWideChar(aCode);
mafVersion := PWideChar(aVersion);
try
AddOnHandle := LoadLibrary(PWideChar(aPath));
if (AddOnHandle <> 0) then
begin
@OpenAddOnFile := GetProcAddress(AddOnHandle, 'OpenAddOnFile');
@CloseAddOnFile := GetProcAddress(AddOnHandle, 'CloseAddOnFile');
if (@OpenAddOnFile <> nil) then
begin
AddOnMainForm := OpenAddOnFile(mafCode, mafFilePath, mafVersion);
AddOnMainForm.Position := poScreenCenter;
AddOnMainForm.ShowModal;
if (@CloseAddOnFile <> nil) then
begin
CloseAddOnFile(mafCode, mafFilePath, mafQuitPopUp);
end;
FreeAndNil(AddOnMainForm);
Application.ProcessMessages;
end;
end;
if not (mafQuitPopUp = PWideChar(EmptyStr)) then
begin
ShowMessage(mafQuitPopUp);
end;
aFilePath := String(mafFilePath);
aCode := String(mafCode);
except
Result := False;
end;
end;
end.
Upvotes: 1
Views: 1329
Reputation: 3768
You could, perhaps, implement it slightly differently with a smallish change to the calling routines in Delphi.
If you were to use the UnmanagedExports (availabe as a Nuget package) as mentioned by David you could get the OpenAddonFile call to return an interface rather than a form. The interface could implement ShowModal and Position.
CloseAddonFile could return an appropriate value as normal. Doesn't matter then whether it's a form a console app or anything else so long as you can call ShowModal on it.
I have found the UnmanagedExports to be very good so long as you remember to only return int / void types from the methods and any strings are returned as var / out parameters.
Upvotes: 1
Reputation: 613461
What you are attempting is impossible. You cannot implement a Delphi form in C#. The code that you posted treats the pointer returned by the DLL function as a Delphi form. The only thing that can implement a Delphi form is code compiled by Delphi.
What's more, your code is not even valid if the DLL is implemented in Delphi. That's because the TForm
class in the host executable is not the same as the TForm
class in the DLL. In order to do what you are attempting to do, with a Delphi DLL, you'd need to pass interfaces across the module boundary.
The bottom line is that your current design for this add-on architecture can never work. You need to go right back to the drawing board and start again.
Upvotes: 4