2012-02-05 15 views
8

この構造体をStructureToPtrで整列化し、PtrToStructureで再び整列化すると、私の最初のノードにはy = {1,2}があり、2番目のノードにはy = {1,0}があります。Barsと固定サイズの配列で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」が1バイトではなく4バイト(BOOL)としてマーシャリングされなければならないかもしれませんか?しかし、私は正確な理由を考えることはできません... – Mehrdad

+0

さらに、最初のものの後の配列要素は無視されます(アンマネージメモリにゼロとして書き込む)。 'bool'が配列の前に来るか構造の後にくるかは関係ありません。 – GSerg

答えて

9

これは本当に間違っています。十分なバイトをコピーできないのはStructureToPtr()呼び出しです。これは、Debug + Windows + Memory + Memory1を使用し、アドレスボックスに "ptr"を入れて見ることができます。 sizeof演算子isn't correctを使用していますが、実際には問題の原因ではありません。配列の長さにかかわらず、配列の最初の要素のみがコピーされます。この問題の原因は不明ですが、ピンボケでと固定されたは決して使用しません。

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); 
    } 

あなたはCLRの相互運用マスターの注意にこれを持参する場合はconnect.microsoft.comに投稿することができます:私は正常に動作し、伝統的なのPInvokeの方法をお勧めすることができます。

+0

あなたが投稿したリンクのコメントは本当に問題を説明していますが、実際の答えは固定サイズのバッファを使用すべきではないことと、MarshalAs属性を使用するだけでよいことです。 私はすでにあなたが実際にsizeof()を使うべきではないことを知っていましたが、現実世界でそれが何か変わるかどうかはわかりません。しかし、とにかく、私は今Marshal.SizeOfを使用するようにコードを変更しました。 – junichiro

+0

@あなたのリンクにコメントがありません☹ –

+0

これに追加するだけです:PtrToStructure()は、メモリ位置に詳細情報が含まれていても、固定配列の最初のバイトだけをコピーします。構造体がLayoutKind.Explicitを使用していてもそれでも失敗します:( –

0

また、使用する前に構造体またはクラスをパックする必要があります。それは私のために、memcpyとほぼ同じくらい役に立ちます

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public class SomeClass 
{ 
} 
関連する問題