C# と C DLL の間での文字列の受け渡し: 最小限の例
問題ステートメント
にもかかわらず一見単純なアプローチに従って、C# と C DLL の間で文字列を渡します。相互運用により System.AccessViolationException が発生します。どちらの言語のコードも正しいように見えますが、問題の根本原因に関して混乱が生じています。
C コード
C コードでは、連結する関数 concat が定義されています。 2 つの文字列を入力し、結果を返します。この関数は、__declspec(dllexport) を使用して DLL にエクスポートするようにマークされています。
extern "C" { string concat(string a, string b){ return a + b; } }
C# コード
C# では、コードは DllImport を使用して concat 関数をインポートします。 CallingConvention は、C の規約に一致するように Cdecl に設定されます。
[DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)] static extern string concat(string a, string b);
例外と分析
C# で concat("a", "b") を呼び出すとスローされます。 System.AccessViolationException。この例外は、ネイティブ コード内で無効なメモリ アクセスが発生していることを示します。
解決策: 相互運用互換型
問題の原因は C std の使用にあります。 ::string が相互運用境界を越えます。 C# では、std::string オブジェクトを直接作成したり処理したりすることはできません。代わりに、相互運用互換型をデータ交換に採用する必要があります。
相互運用対応のデータ型
適切な相互運用型には、文字列を渡すための null で終了する文字配列が含まれます。 C# から C へ。 C から C# に文字列を渡す場合、呼び出し側がバッファを割り当て、呼び出し先がバッファに書き込む StringBuilder を使用できます。
修正コード
C では、 concat 関数は、char* および int パラメーターを使用して宣言して、バッファーとそのバッファーを受け取ることができます。
extern "C" { void concat(char *str, int len) { // Concatenate strings and write to buffer } }
C# では、StringBuilder を利用できます。
[DllImport("...", CallingConvention = CallingConvention.Cdecl)] static extern void concat(StringBuilder str, int len); .... StringBuilder sb = new StringBuilder(10); concat(sb, sb.Capacity);
相互運用互換性のある文字列型を使用することにより、C# と C DLL の間の文字列の交換が容易になります。効果的に。
以上がC# と C DLL の間で文字列を渡すときに System.AccessViolationException を回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。