【问题标题】:Marshalling part of a struct编组结构的一部分
【发布时间】:2014-06-13 12:27:28
【问题描述】:

我一直试图弄清楚是否可以将结构的一部分编组为字节数组而不会出现任何错误。这样做的原因是因为不会编组的部分有一个可变大小的数组。这是我正在使用的代码。

C#:

public struct Random { 
    [MarshalAs(UnmanagedType.I4)]
    public int a;
    [MarshalAs(UnmanagedType.I4)]
    public int b;
    [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_RECORD)]
    public Random1[] r;
}

public struct Random1 { 
    [MarshalAs(UnmanagedType.I4)]
    public int c;
}

private void Form1_Load(object sender, EventArgs e) {
    int size = Marshal.SizeOf(typeof(Random));
    int s = 4;
    Random r = new Random();
    Random r1 = new Random();

    r.a = 1;
    r.b = 5;
    r.r = new Random1[2];
    r.r[0].c = 10;
    r.r[1].c = 12;

    IntPtr p = Marshal.AllocHGlobal(size);
    try {
        byte[] arr = new byte[size];
        Marshal.StructureToPtr(r, p, false);
        Marshal.Copy(p, arr, 0, 8);
        Marshal.FreeHGlobal(p);
        p = Marshal.AllocHGlobal(size);
        Marshal.Copy(arr, 0, p, 8);
        r1 = (Random) Marshal.PtrToStructure(p, typeof(Random));
        Marshal.FreeHGlobal(p);
        p = IntPtr.Zero;
        Debug.WriteLine(r1.a);
        Debug.WriteLine(r1.b);
        Debug.WriteLine(r1.r[0].c);
        Debug.WriteLine(r1.r[1].c);
    } finally {
        if (p != IntPtr.Zero) {
            Marshal.FreeHGlobal(p);
        }
    }
}

当我尝试这段代码时,它会在 StructureToPtr 中给我一个 ArgumentException。我做错了什么或者可以这样做吗?如果没有,我已经阅读了有关使用 IntPtr 的内容。谁能告诉我该怎么做?

【问题讨论】:

  • ArgumentException 说明了什么?
  • 这是消息参数不正确。 (HRESULT 异常:0x80070057 (E_INVALIDARG))
  • 这里的问题是SafeArray,interop 不太知道如何处理。
  • 使用固定大小的数组解决了。

标签: c# arrays struct marshalling


【解决方案1】:

我一直在努力思考这个问题,在尝试了几个(非常 hackish)选项之后,我得出的结论是你所做的事情是不可能的。

首先,不可能直接封送变长数组,因为无法通过 Marshal 计算出有意义的大小偏移量,因此无法确定内存布局。

如果结构不包含任何非 blittable、非原始类型,理论上你可以这样做:

byte[] buffer = new byte[8];
Marshal.Copy(new IntPtr(&r), buffer, 0, 8);

IntegersOnlyStruct partialStruct;
fixed (byte* b = buffer)
    partialStruct = *(IntegersOnlyStruct*) b;

并以这种方式获取结构中包含的两个整数。但是,由于您的 Random1 是非原始、不可 blittable 类型,因此这种方法也不会让您走得太远。

IntPtr 方法将指针指向您的 Random1 结构保存在内存中的内存位置是一种可能可行的替代方法,但我还没有深入探讨。

我认为您可能需要重新考虑处理此问题的方式,因为目前的形式是不可能的。如果有人可以证明并非如此,我很乐意看看如何做到这一点。

【讨论】:

  • 谢谢。我已经通过使用固定大小的数组解决了这个问题。但正如你所说,我想知道是否有可能
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-02
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
相关资源
最近更新 更多