[英]Using Delphi DLL in C#
我有一個用Delphi(未知版本)編寫的第三方“神秘dll”,在delphi(2009年)中的工作示例,急需在我的C#代碼中使用所述dll,並且幾乎沒有關於如何執行它的相關知識。
以下是使用此dll的Delpi示例:
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;
這是我嘗試用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");
}
}
不幸的是,我所擁有的是一個錯誤:嘗試讀取或寫入受保護的內存。 這通常表明其他內存已損壞。
從我白天讀到的內容來看,我可能會對返回類型或參數類型進行捏造。 救命?
對於某些類型,Delphi ABI與Microsoft ABI不同。 Delphi WideString
是托管類型(在Delphi術語中),並且返回類型使用與Microsoft工具不兼容的ABI。
Delphi ABI將托管返回類型轉換為隱藏的var
參數。 所以編譯器轉換:
function(host: WideString; port: Word; pud, query: WideString): WideString; stdcall;
成
procedure(var result: WideString; host: WideString; port: Word; pud, query: WideString);
stdcall;
因此,您可以通過導入轉換后的偽裝中的函數從C#訪問原始的Delphi函數。
[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
);
我大多想通了。 由於某些原因我不清楚,C#不能處理WideString返回值。 如果您可以訪問delphi源代碼,則可以使用procedure交換函數,並將返回值作為“out”參數傳遞。 在我的情況下,我沒有訪問源,所以我被迫編寫代理DLL來這樣做。 例如上面的“代理”DLL代碼:
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;
然后用C#代碼訪問它:
[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
);
它不漂亮,但對我來說,這是答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.