1

与えられた C++ ライブラリにアクセスする .NET DLL に取り組んでいます。C++ ライブラリには、次の構造体があります。

typedef struct FOO
{
    DWORD DataSize;
    BYTE  *pData;
}

したがって、C#で再作成しました:

[StructLayout(LayoutKind.Sequential)]
public struct FOO
{
    public uint DataSize;
    public byte[] pData;
}

次は、C++ DLL からのインポートです。C++ 側のヘッダーもインクルードします。C++ のメソッドは、渡す構造体へのポインターを受け取るため、収集できたものから参照を渡すと、この場合は機能します。

// C++ Header
HRESULT CallFoo(FOO * pFoo);

[DllImport("SomeLibrary.DLL", EntryPoint = "CallFoo")]
private static extern uint CallFoo(ref FOO rFoo);

C++ 側のコードにステップ インすると、構造体が取得されますが、pData の値はメモリ アドレスです。これは C++ ライブラリのコードを汚しているように見えますが、返された HRESULT を理解できません (エラー メッセージについて、C++ ライブラリの所有者に質問しました)。

この質問の回答に基づいて私が取った別のアプローチは、バイト配列の代わりに IntPtr を渡すことでした。構造体を変更しました:

[StructLayout(LayoutKind.Sequential)]
public struct FOO
{
    public uint DataSize;
    public IntPtr pData;
}

そしてそれを呼び出す:

FOO fooParm = new Foo();
var ptr = IntPtr.Zero;
byte[] bArr = MethodThatReturnsAByteArray();

ptr = Marshal.AllocHGlobal(bArr.Length);
Marshal.Copy(bArr, 0, ptr, bArr.Length);

fooParm.pData = ptr;
fooParm.DataSize = bArr.Length;

uint i = CallFoo(fooParm);

残念ながら、これも機能していません。元のアプローチと同じエラー コードが表示されます。

4

2 に答える 2

1

目の前にC++ライブラリがないので、この質問に正確に答えるのは難しいと思いますが、ポインタを取得しているようで、ライブラリに問題があります。そのポインタを適切なMarshal::PtrToStructureものにマップするために使用することは可能でしょうか?byte[]struct

これが私が話している特定の方法へのリンクです。下部にある2番目のコード例(C ++)が適用される場合があります:http://msdn.microsoft.com/en-US/library/4ca6d5z7.aspx

于 2012-10-12T06:42:29.187 に答える
1

あなたの全体的なアプローチは良くありません。管理された構造体/クラスのレイアウトに関する情報がありますが、使用しない方がよいでしょう。これを試してください:

[DllImport("SomeLibrary.DLL", EntryPoint = "CallFoo")]
private static extern uint CallFoo(uint DataSize, IntPtr pData);

やり取りするパラメータが単純であればあるほど、結果は良くなります。

于 2012-10-12T06:37:17.987 に答える