传递给结构中的非托管代码时,C#中的字节数组会发生什么?

时间:2012-10-12 06:08:58

标签: c# c++ arrays struct unmanaged

我正在研究.NET DLL来访问我给出的C ++库。在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 ++库的所有者提出了一个问题,即错误消息是什么)。 / p>

我基于this question's answer采用的另一种方法是尝试传递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);

遗憾的是,这也不起作用。我得到了与原始方法相同的错误代码。

2 个答案:

答案 0 :(得分:1)

你的整个方法并不好。有关托管结构/类的布局的一些信息,但最好不要使用它。尝试这样做:

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

您来回传递的参数越简单,结果就越好。

答案 1 :(得分:1)

我没有面对我的C ++库,所以我觉得很难准确回答这个问题,但听起来你得到一个指针而且库有问题。是否可以使用Marshal::PtrToStructurebyte[]指针映射到正确的struct

这是我正在谈论的特定方法的链接。靠近底部的第二个代码示例(在C ++中)可能适用:http://msdn.microsoft.com/en-US/library/4ca6d5z7.aspx