p/invokeコードとDelphiコードの間に不一致があります。あなたはDelphiコードを表示していませんが、C#コードはDelphiコードの外観を知るには十分です。
DllImport
属性は、呼び出し規約と文字セットのデフォルト値を使用します。つまり、呼び出し規約はstdcall
で、文字セットはANSIです。マーシャリング属性を指定していないので、デフォルトのマーシャリングを使用する必要があります。
したがって、あなたのDelphiのコードは次のようになります。
function MyMethod(someStringParam: PChar): PChar; stdcall;
begin
Result := ??;
end;
そして今、ここで問題です。 p/invoke marshallerはstring
の戻り値を非常に特別な方法で扱います。戻り値のメモリを解放するのは、p/invoke marshallerの責任であると想定しています。また、ネイティブコードと同じアロケータを使用する必要があります。マーシャラーによって行われる前提は、共有COMアロケーターが使用されることです。
したがって、ネイティブコードは、CoTaskMemAlloc
を呼び出すことによってCOMアロケータでメモリを割り当てる必要があります。私の賭けはあなたのコードはそれをしないし、それは確かにエラーにつながるということです。
ここでは、コード内のC#シグネチャで動作するネイティブのDelphi関数を作成する方法の例を示します。
function MyMethod(someStringParam: PChar): PChar; stdcall;
var
Size: Integer;
begin
Size := SizeOf(Char)*(StrLen(someStringParam)+1);//+1 for zero-terminator
Result := CoTaskMemAlloc(Size);
Move(someStringParam^, Result^, Size);
end;
あなたがこのアプローチを採用する可能性がなくなり、私は選択肢をお勧めします。すべての文字列をC#側にBSTR
、デルファイ側にWideString
とマーシャリングします。これらは、COMアロケータによって割り当てられる一致する型です。両方の当事者は、これらのタイプをどうするかを正確に知っており、あなたの人生をより楽にします。
デルファイは関数の戻り値に異なるABIを使用するため、残念ながら、interop境界を越えてDelphi関数からWideString
を返すことはできません。この問題の詳細は私の質問にありますWhy can a WideString not be used as a function return value for interop?
これを回避するには、Delphiコードの戻り型をTBStr
と宣言できます。あなたのコードを次のようになります。
C#
[DllImport(@"MyDll.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string MyMethod(
[MarshalAs(UnmanagedType.BStr)]
string someStringParam
);
デルファイ私にとって
function MyMethod(someStringParam: WideString): TBStr; stdcall;
begin
Result := SysAllocString(POleStr(someStringParam));
end;
DLL内の関数の呼び出し規約は何ですか? – ain
Delphiメソッドのコードを表示してください –
Delphiでの関数の宣言は、C#の対応するものとは異なります –