簡體   English   中英

Marshal.PtrToStructure<T> (IntPtr ptr, T 結構) 拋出 [System.ArgumentException]: 該結構不能是值類

[英]Marshal.PtrToStructure<T>(IntPtr ptr, T structure) throws [System.ArgumentException]: The structure must not be a value class

我認為 C# 方法中可能存在錯誤

Marshal.PtrToStructure<T>(IntPtr ptr, T structure)

我錯誤地認為T structure意味着您可以傳入您想要填充的結構,但是當我在下面的示例中執行此操作時會引發異常:

[System.ArgumentException:結構不能是值類。 參數名稱:結構]

給你一個簡單的例子:

using System;
using System.Runtime.InteropServices;

public class Program
{
    public static void Main()
    {
        MyStruct s = new MyStruct();

        var buffer = new Byte[]{1,2,3};
        var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        Marshal.PtrToStructure<MyStruct>(handle.AddrOfPinnedObject(), s);
        handle.Free();
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct MyStruct
    {
        public Byte a;
        public Byte b;
        public Byte c;
    }
}

我讀錯了方法聲明嗎? 還是有bug?

[StructLayout(LayoutKind.Sequential, Pack = 1)]
class MyStruct
{
    public Byte a;
    public Byte b;
    public Byte c;
}

我自己有這個問題,發現將結構更改為類(引用類型)就出現了問題。

參數名稱structure在這里具有誤導性。 文檔兩次調用它必須是一個類。

結構類型。 這必須是格式化的類。

您不能將此方法重載用於值類型。

然而,當它說的時候,它也自相矛盾

結構布局不是順序的或明確的。

查看實際來源,您沒有找到where T : class約束,我猜應該存在文檔。

不是將您的結構轉換為類(或記錄,我認為),而是在 4.5.1 和更新版本(和 .NET 核心)中有一個新的重載,它使用結構對我有用。

var msgReceived = new FixedLengthStruct();
unsafe
{
  fixed(byte* buffer = memoryAccessor.Bytes)
  {
    msgReceived = Marshal.PtrToStructure<FixedLengthStruct>((IntPtr)buffer);
  }
}
// Process msgReceived

我的結構在這里使用了 LayoutKind.Explicit。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM