Using Delphi DLL in C#

前提是你 提交于 2019-12-05 08:21:58

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
);

I mostly figured it out. For some reason unclear to me, C# cant handle WideString return values. If you have access to delphi source code, it might be appropriate to exchange function with procedure, and pass return value as "out" parameter. In my case, I did not have access to source, so I was forced to write a proxy DLL to do so. For example above, "proxy" dll code:

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

procedure My_D_Query(host: WideString; port: Word; pud, query: WideString; out return : WideString); stdcall;
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,port,pud,query);
  FreeLibrary(Handle);
 end;
return := sss;
end;

Then C# code to access it:

[DllImport("C:\\MyDll.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
public static extern void My_D_Query(
[MarshalAs(UnmanagedType.BStr)]
        string host,
        int port,
[MarshalAs(UnmanagedType.BStr)]
        string pud,
[MarshalAs(UnmanagedType.BStr)]
        string query,
[MarshalAs(UnmanagedType.BStr)]
        out string result
);

Its not pretty, but for me, it was the answer.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!