0

C#でP/InvokeであったC++APIから正しいデータを取得する際に問題が発生しました。C ++関数は、要求されたデータ、サイズ、および取得する正確なパラメーターを格納するためのポインターを取得するように設定されています。明らかに私の設定に何か問題があり、提案を探しています。ありがとうございました!

C ++プロト:

DECL_FOOAPIDLL DWORD WINAPI FOO_GetVal(
VOID *Val,  //pointer to memory where the data will be stored by the function
DWORD Len,  //length of Val in bytes
DWORD Id    //identification number of the parameter
);

C#P / Invoke署名:

[DllImport(FOO_API, CharSet = CharSet.Auto)]
static public extern uint FOO_GetVal(IntPtr val, uint len, uint id);

設定に関する情報を取得するための私のC#コード:

IntPtr Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
uint hr = FOOWrapper.FOO_GetVal(Ptr, (uint)Marshal.SizeOf(Ptr), FOOWrapper.CMD_RUNNING);
int result = Marshal.ReadInt32(Ptr);
Marshal.FreeHGlobal(Ptr);

したがって、大きな問題は、Marshal.ReadInt32()を介して返されたポインターを正しく読み取っていますか?

前もって感謝します!

4

1 に答える 1

1

pinvoke宣言に問題はありません。使用方法が正しくありません。IntPtr用のスペースを予約していますが、intを読み取っています。適切なコードは次のようになります。

uint len = (uint)Marshal.SizeOf(typeof(int));
IntPtr ptr = Marshal.AllocHGlobal(len);
uint hr = FOOWrapper.FOO_GetVal(ptr, len, FOOWrapper.CMD_RUNNING);
if (hr != 0) throw new COMException("FOO_GetVal failed", hr);
int result = Marshal.ReadInt32(ptr);
Marshal.FreeHGlobal(ptr);

追加は重要です。エラーリターンコードを無視したくないことは確かです。それが実際にエラーコードである場合、「hr」の使用はそれがそうであることを示唆しますが、宣言はそうではないことを示唆します。実際のデータのサイズである場合は、次のように変更します。

uint actual = FOOWrapper.FOO_GetVal(ptr, len, FOOWrapper.CMD_RUNNING);
if (actual != len) throw new Exception("Improper data size");

これはさらに、要求しているパラメーターが実際にはintであることを前提としています。言うことはできませんが、「CMD_RUNNING」は、C++では1バイトのブール値のように聞こえます。

これをデバッグして、問題が何であるかを調べてください。[プロジェクト+プロパティ]の[デバッグ]タブで[アンマネージコードのデバッグを有効にする]チェックボックスをオンにします。そして、ネイティブコードのFOO_GetVal()関数にブレークポイントを設定します。

于 2012-08-29T22:54:23.587 に答える