2016-07-05 10 views
5

私はデルファイ(未知のバージョン)、デルファイ(過去2009年)で動作する第三者 "ミステリーdll"、C#コードで上記のdllを使用する悲惨な必要性、それを行う方法について。ここでC#でDelphi 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"); 
    } 
} 

は残念ながら、私が持っているとするとエラーになり:しようとしまし読むためにまたは書き込み保護されたメモリ。これはしばしば、他のメモリが壊れていることを示します。

私は1日中に読んだことから、おそらく戻り値の型、またはパラメータ型を参照することになりました。助けて?

+0

あなたの呼び出し規約が他の問題の中で間違っているようです。私はデルファイの専門家ではないが、これは助けるかもしれないhttp://stackoverflow.com/questions/16601423/calling-a-delphi-method-in-a-dll-from-c-sharp –

+0

Eww、DLL関数は決して戻ってはならない問題の原因となる可能性のあるあらゆるタイプの文字列。 –

+0

このDelphi DLLがShareMemを使用する可能性はありますか? –

答えて

5

デルファイ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 
); 
0

私はほとんどそれを理解しました。私に不明な何らかの理由で、C#はWideStringの戻り値を扱えません。あなたがデルファイのソースコードにアクセスできるなら、手続きと関数を交換し、戻り値を "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 
); 

そのかなりが、私のためではない、それが答えでした。

+0

@MBoが投稿したリンクは見ましたか? AFAICSでは、WideStringの戻り値**は実際には既に**のパラメータであり、C#側ではそのように宣言する必要があります。私はまずそれを試してみるだろう。 –

+0

プロキシDLLは必要ありません。私の答えを見てください。つまり、プロキシDLLはトリッキーなインポートに対処するきれいな方法ですが、ここでは必要ありません。また、 'Word'は' ushort'にマップされます。 –

+0

@DavidHeffernanあなたが提案したようにプロキシDLLを取り除こうとしましたが、「保護されたメモリを読み書きしようとしました」ということが続きます。エラー。 intをushort btwに変更しました。 –

関連する問題