从非托管内存中的字节读取字符数组

时间:2014-01-07 09:46:21

标签: c# pinvoke marshalling

我正在将一个原生的32位代码编组到c#,因为在联盟内部的结构中混合了value-type成员和reference-type成员,我将所有引用类型转换为字节并解决了它们的大小通过使用fielOffset ..现在我想访问其中一个成员的值,我不知道如何做到这一点。以下代码为样本。

这是c ++结构

typedef struct
  {    
    int Port;
    char SubsId[FIELD_SIZE_SUBS_ID+1];
    char Options[FIELD_SIZE_OPTIONS+1];
  } MMTPRcnxReq;

这是c#等价物

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
public struct MMTPRcnxReq
{
    [FieldOffset(0)] 
    public Int32 Port;

    [FieldOffset(4)] 
    public byte SubsId;

    [FieldOffset(4 + FIELD_SIZE_SUBS_ID + 1)] 
    public byte Options;
}

现在我想访问SubId的值,它实际上是一个字符数组,并且例如将它与我的托管代码中的字符串进行比较, 如下所示

if(mMTPRcnxReq.SubsId == "12345") // WRONG

我该怎么做?

1 个答案:

答案 0 :(得分:2)

您可能需要在此使用固定大小缓冲区的unsafe

unsafe struct MMTPRcnxReq
{
    public int Port;
    public fixed byte SubsId[FIELD_SIZE_SUBS_ID+1];
    public fixed byte Options[FIELD_SIZE_OPTIONS+1];
}

固定大小的缓冲区是一个值类型,它允许您将其中一个结构放在FieldOffset(0) C#联合中。

阅读如下字符串:

string SubsId;
unsafe
{
    fixed (byte* ptr = req.SubsId)
    {
        // I presume that req.SubsId is null-terminated
        SubsId = Marshal.PtrToStringAnsi((IntPtr)ptr);
    }
}

您可能会编写结构的辅助getter和setter方法(可能作为属性)来管理固定大小的缓冲区。