2012-02-06 21 views
0
私は次の関数いる

:そして、私はこのようなC#のからそれをこのC++関数を呼び出す方法は?

bool __declspec(dllexport) COMS_HL7QueryAnswer(char *szZone,char* szMessage, char** o_szAnswer) 

をPInvokingよ:

public static extern bool COMS_HL7QueryAnswer(string szZone,string szMessage, out StringBuilder szAnswer); 
これは、Windows 2003で働いていますが、私はW2008とルックスでアクセス違反の例外を取得しています

彼らはPInvokeの境界で起こるように。どんな助けも素晴らしいでしょう。

ありがとうございました。

編集:私はC#の機能以外のコールスタックを持っていない

  1. :ので、AccessViolationExceptionがPInvokeの境界で起こるようが見えます。
  2. デバッガを使用すると、最後のC++関数までF10できます。終了すると、C#例外ハンドラに移動します。
+0

境界**で発生しているように見えます。追加情報が正確にどのように失敗したかは参考になります。 –

+0

@Ramhound:私の編集をご覧ください。ありがとう。 –

+0

あなたの署名が有効でないことを除いて、あなたの呼び出し規約も一致しません。解決したいかもしれません。 –

答えて

3

あなたはP /呼び出しがどのように正しく*o_szAnswer無料のないアイデアを持っていないので

[DllImport(CallingConvention = CallingConvention.Cdecl)] 
public static extern bool COMS_HL7QueryAnswer(string szZone,string szMessage, out IntPtr szAnswer); 

を使用する必要がありますが、あなたは」の後、自分でポインタを維持し、正しい解放関数にそれを渡す必要がありますデータを取り出す。

C++側を変更することが許可されている場合は、p/invoke-friendlyにするためにできることがいくつかあります。または、C++/CLIレイヤーを使用することもできます。

+0

StringBuilderをGCしたときにCLRが解放されない理由* szAnswer?まあ、多分* szAnswerは何かグローバルなのでしょうか? –

+1

@ SoMoS: '* o_szAnswer'は、C++コード内のいくつかのバッファのアドレスに割り当てられました。 CLRはそのバッファから 'StringBuilder'に読み込むことができますが、バッファを解放する方法はわかりません。だからそれを解放しようとするか、間違った割り当て解除関数を推測するか、アクセス違反が発生するか、何もせずにメモリリークが発生します。 –

+0

@ SoMoS:Cスタイルの文字列である '* o_szAnswer'を意味していました。申し訳ありませんが、それはあなたに混乱を引き起こした場合。 'StringBuilder'オブジェクトはガベージコレクトされますが、データはC++を離れるときに' StringBuilder'にはありません。 –

1

コードがメモリにリークしています。はい、W2003はピンボケ・マーシャラーが文字列を解放しようとしたことを静かに無視します。 W2008ははるかに厳しいメモリマネージャーを持ち、それに気を配りませんが、アクセス違反を引き起こします。 IntPtrとMarshal.PtrToStringAnsi()を使用してメモリをリークし続けることができます。 Cコードを修正することができれば、CoTaskMemAlloc()で文字列バッファを割り当てても問題は解決しますが、pinvoke marshallerはCoTaskMemFree()を使用します。

実際の修正は、char **の代わりにchar *であるため、呼び出し元は、文字列でいっぱいになるバッファを渡すことができます。 StringBuilderなしでからC#​​。容量を与える追加の引数を使用すると、文字列が収まらないときに偶然に収集されたガーベージ・ヒープを破損させません。

+0

'out IntPtr'を使うと、彼のコードは解放関数に渡す正しいポインタを持っています。 –

関連する問題