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

What happens to a byte array in C# when passed to unmanaged code in a struct?

本文关键字:非托管代码 什么情况 结构 字节 字节数 数组      更新时间:2023-10-16

我正在开发一个.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++库的所有者提出了一个问题,询问错误消息是什么)。

基于这个问题的答案,我采取的另一种方法是尝试传递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);

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

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

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

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

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

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