Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Delphi DLL in C#

I have a third party "mystery dll" written with Delphi(unknown version), working example in delphi (past 2009), dire need to use said dll in my C# code, and almost no relevant knowledge on how to do it.

Here is Delpi example in using this dll:

type
TD_Query = function(host: WideString; port : Word;pud,query : WideString):WideString; stdcall;
procedure TForm11.Button6Click(Sender: TObject);
var
   Handle         : LongWord;
   D_Query        : TD_Query;
   sss            : WideString;
begin

 Handle := LoadLibrary('kobrasdk.dll');
 sss:='';
 if Handle <> 0 then
 begin
  @D_Query := GetProcAddress(Handle, 'D_Query');
  sss:=D_Query('host',8201,'pud','query');
  FreeLibrary(Handle);
 end;
end;

And here is my attempts to interpret it in C#:

class Program
{
    [DllImport("C:\\Games\\kobrasdk.dll", CallingConvention = CallingConvention.StdCall,
        CharSet = CharSet.Ansi)]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string D_Query(string host, ushort port, string pud, string query);


    static void Main(string[] args)
    {
        D_Query("test", 8201, "test", "test");
    }
}

Unfortunately, what I have is an error: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

From what I read during the day, I probably fudged up with return type, or parameter types. Help?

like image 998
Morhem Howk Avatar asked Jul 05 '16 17:07

Morhem Howk


1 Answers

The Delphi ABI differs from the Microsoft ABI for certain types. A Delphi WideString is a managed type (in Delphi terminology) and as return types use an ABI that is incompatible with Microsoft tools.

The Delphi ABI translates a managed return type into a hidden var parameter. So the compiler transforms:

function(host: WideString; port: Word; pud, query: WideString): WideString; stdcall;

into

procedure(var result: WideString; host: WideString; port: Word; pud, query: WideString); 
  stdcall;

You can therefore access your original Delphi function from C# by importing the function in its transformed guise.

[DllImport(@"...", CallingConvention = CallingConvention.StdCall)]
public static extern void My_D_Query(
    [MarshalAs(UnmanagedType.BStr)]
    out string result,
    [MarshalAs(UnmanagedType.BStr)]
    string host,
    ushort port,
    [MarshalAs(UnmanagedType.BStr)]
    string pud,
    [MarshalAs(UnmanagedType.BStr)]
    string query
);
like image 74
David Heffernan Avatar answered Oct 13 '22 03:10

David Heffernan