2012-10-12 32 views
1

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

我根据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); 

这不幸的是不工作要么。我得到与原始方法相同的错误代码。

回答

1

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

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

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

+0

我不想使用这些自定义结构,但不幸的是该库不是我控制的东西。我已经为它编写了一个托管的C++包装器,我可能可以在调用库之前处理翻译,我也会看看这种方法。 – Wint

1

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

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

+0

我下班时会仔细看看今晚的情况。我尝试过的另一个方法是我没有提到将整个结构作为IntPtr传递,也许我需要再次重新访问该方法。 – Wint

相关问题