user1889268
user1889268

Reputation:

PInvoke & Delphi

How can i use this dll function in c#? I tried the following but i get error. "External component has thrown an exception."

First time i am doing this PInvoke stuff with C# and Delphi.

function HTTPGET(location:string):string; stdcall;
var
HTTP:TIdHttp;
begin
  HTTP := TidHttp.Create(nil);
  try
    result := HTTP.Get(location);
  finally
  FreeAndNil(HTTP);
  end;
end;


exports
  HTTPGET;

begin
end.


namespace Test
{
    class Program
    {
        [DllImport("project1.dll")]
        public static extern string HTTPGET(string location);

        static void Main(string[] args)
        {
           Console.WriteLine(HTTPGET("http://www.reuters.com/"));
        }
    }
}

Upvotes: 1

Views: 1199

Answers (4)

Lightning3
Lightning3

Reputation: 375

Try Unmanaged Exports for c# by Robert Giesecke

https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

we are using encrypting engine from c# in Delphi App due compatibility with php and works well (so, the mentioned strings problem do not exists).

our earlier solution (worse) : register c# dll as com component and use it. with above solution output library have to be placed in exe directory and without registration works well :)

Upvotes: -1

David Heffernan
David Heffernan

Reputation: 613441

You cannot call that function from C#. That's because you cannot use Delphi string for interop. You can use PAnsiChar for strings passed from managed to unmanaged, but in the other direction it's more complex. You'd need to allocate the memory at the caller, or use a shared heap. I prefer the latter approach which is easiest done with the COM BSTR. This is WideString in Delphi.

As has been discussed before, you cannot use WideString as a return value for interop, since Delphi uses a different ABI from MS tools for return values.

The Delphi code needs to look like this:

procedure HTTPGET(URL: PAnsiChar; out result: WideString); stdcall;

On the C# side you write it like this:

[DllImport("project1.dll")] 
public static extern void HTTPGET(
    string URL,
    [MarshalAs(UnmanagedType.BStr)]
    out string result
);     

If you want Unicode for the URL then use PWideChar and CharSet.Unicode.

procedure HTTPGET(URL: PWideChar; out result: WideString); stdcall;
....
[DllImport("project1.dll", CharSet=CharSet.Unicode)] 
public static extern void HTTPGET(
    string URL,
    [MarshalAs(UnmanagedType.BStr)]
    out string result
);     

Upvotes: 7

thalm
thalm

Reputation: 2930

As i remember, you can't marshall delphi strings with C#... you have to use a workaround with PChar and manage the memory yourself, or use something like the workaround provided in the last answer here:

Using Delphi's stuct arrays and strings in C#

Upvotes: -1

nullptr
nullptr

Reputation: 11058

Do not use string type: strings require memory management, and C# and Delphi modules obviously use different memory managers (leave alone that C# passes char* and Delphi expects String). Try changing location type to PChar in your DLL, and also change your result type so it's either PChar (the buffer should be allocated explicitly) or something else, but not string.

Upvotes: 0

Related Questions