2012-02-05 28 views
8

如果我用StructureToPtr編組這個結構,然後再用PtrToStructure解組它,我的第一個節點有y = {1,2},而我的第二個節點有y = {1,0}。Marshal.StructureToPtr失敗與布爾和固定大小的數組?

我不知道爲什麼,也許我的結構不好?從結構中刪除bool使其工作。

using System; 
using System.Runtime.InteropServices; 

namespace csharp_test 
{ 
    unsafe class Program 
    { 
     [StructLayout(LayoutKind.Sequential)] 
     public struct Node 
     { 
      public bool boolVar; 
      public fixed int y[2]; 
     } 

     unsafe static void Main(string[] args) 
     { 
      Node node = new Node(); 

      node.y[0] = 1; 
      node.y[1] = 2; 
      node.boolVar = true; 

      int size = sizeof(Node); 
      IntPtr ptr = Marshal.AllocHGlobal(size); 
      Marshal.StructureToPtr(node, ptr, false); 
      Node node2 = (Node)Marshal.PtrToStructure(ptr, typeof(Node)); 
      Marshal.FreeHGlobal(ptr); 
     } 
    } 
} 
+0

也許它必須做一些事情,把'bool'編組爲4字節('BOOL')而不是1個字節?但我想不出確切的原因...... – Mehrdad 2012-02-05 19:37:07

+0

此外,它忽略了第一個數組元素之後的任何數組元素(將它們作爲零寫入非託管內存中)。如果'bool'出現在陣列之前或結構之後,也沒有關係。 – GSerg 2012-02-05 19:42:29

回答

9

這的確是出了問題。這是StructureToPtr()調用無法複製足夠的字節。你可以通過使用Debug + Windows + Memory + Memory1並在地址欄中輸入「ptr」來看到這一點。使用sizeof運算符isn't correct但實際上不是問題的根源。無論數組長度如何,只有數組的第一個元素被複制。不知道是什麼原因導致這個問題,我從來沒有用固定在pinvoke。我只能推薦傳統的PInvoke方法的正常工作:如果你希望把這種對CLR互操作高手的關注,您可以張貼到connect.microsoft.com

unsafe class Program { 
    [StructLayout(LayoutKind.Sequential)] 
    public struct Node { 
     public bool boolVar; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] 
     public int[] y; 
    } 

    unsafe static void Main(string[] args) { 
     Node node = new Node(); 
     node.y = new int[2]; 

     node.y[0] = 1; 
     node.y[1] = 2; 
     node.boolVar = true; 

     int size = Marshal.SizeOf(node); 
     IntPtr ptr = Marshal.AllocHGlobal(size); 
     Marshal.StructureToPtr(node, ptr, false); 
     Node node2 = (Node)Marshal.PtrToStructure(ptr, typeof(Node)); 
     Marshal.FreeHGlobal(ptr); 
    } 

+0

謝謝,您發佈的鏈接中的評論確實可以解釋問題,但實際上真正的答案是我不應該使用固定大小的緩衝區,而應該使用MarshalAs屬性,如您所示。 我已經意識到你不應該真的使用sizeof(),只是我不確定是否在真實世界中它有什麼區別。但無論如何,我已經改變了我的代碼使用Marshal.SizeOf無論如何。 – junichiro 2012-02-05 20:19:56

+0

@Han缺少鏈接中的註釋☹ – 2014-10-14 09:47:10

+0

只需添加到此:即使內存位置包含更多信息,PtrToStructure()也將僅複製固定數組的第一個字節。即使結構使用LayoutKind.Explicit它仍然失敗:( – 2016-02-05 09:29:59

0

在使用它之前,您還應該打包結構或類。這適用於我,幾乎和memcpy一樣好

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public class SomeClass 
{ 
}