回答編集履歴

2

修正

2020/11/04 05:28

投稿

退会済みユーザー
test CHANGED
@@ -27,6 +27,10 @@
27
27
  Marshalクラスや、PInvoke呼び出しを経由する分には、マーシャリングで上手く変換してくれるのですが、非Blittableな構造体の実際のメモリの配置のされ方は、C言語の構造体とは違います。
28
28
 
29
29
 
30
+
31
+ 下記のコードをデバッグ実行して、Console.ReadLineの辺りにブレークポイントを設定し、デバッグ⇒ウィンドウ⇒メモリでptr1,ptr2の指すメモリ内のデータの配置のされ方を覗いたり、変数の値を覗いたりしてみてください。
32
+
33
+ 何故上手くいかないのか理由が判ると思います。
30
34
 
31
35
  ```csharp
32
36
 
@@ -137,7 +141,3 @@
137
141
  }
138
142
 
139
143
  ```
140
-
141
- デバッグ実行してConsole.ReadLineの辺りにブレークポイントを設定し、デバッグ⇒ウィンドウ⇒メモリでptr1,ptr2の指すメモリ内のデータの配置のされ方を覗いたり、変数の値を覗いたりしてみてください。
142
-
143
- 何故上手くいかないのか理由が判ると思います。

1

追記

2020/11/04 05:28

投稿

退会済みユーザー
test CHANGED
@@ -17,3 +17,127 @@
17
17
  };
18
18
 
19
19
  ```
20
+
21
+
22
+
23
+ 固定ではない配列を含む構造体は、非Blittable型になります。
24
+
25
+ [Blittable 型と非 Blittable 型](https://docs.microsoft.com/ja-jp/dotnet/framework/interop/blittable-and-non-blittable-types)
26
+
27
+ Marshalクラスや、PInvoke呼び出しを経由する分には、マーシャリングで上手く変換してくれるのですが、非Blittableな構造体の実際のメモリの配置のされ方は、C言語の構造体とは違います。
28
+
29
+
30
+
31
+ ```csharp
32
+
33
+ class Program
34
+
35
+ {
36
+
37
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
38
+
39
+ public unsafe struct Data1
40
+
41
+ {
42
+
43
+ public uint member1;
44
+
45
+ public uint member2;
46
+
47
+ public fixed uint member3[128];
48
+
49
+ };
50
+
51
+
52
+
53
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
54
+
55
+ public struct Data2
56
+
57
+ {
58
+
59
+ public uint member1;
60
+
61
+ public uint member2;
62
+
63
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
64
+
65
+ public uint[] member3;
66
+
67
+ };
68
+
69
+
70
+
71
+ static void Main(string[] args)
72
+
73
+ {
74
+
75
+ try
76
+
77
+ {
78
+
79
+ unsafe
80
+
81
+ {
82
+
83
+ var dat1 = new Data1();
84
+
85
+ dat1.member1 = 1;
86
+
87
+ dat1.member2 = 2;
88
+
89
+ for (uint i = 0; i < 128; i++)
90
+
91
+ {
92
+
93
+ dat1.member3[i] = i;
94
+
95
+ }
96
+
97
+
98
+
99
+ var ptr1 = &dat1;
100
+
101
+ var dat2 = Marshal.PtrToStructure<Data2>((IntPtr)ptr1);
102
+
103
+ //var ptr2 = &dat2; //これはコンパイルエラー
104
+
105
+ var ptr2 = Unsafe.AsPointer(ref dat2);
106
+
107
+ var span1 = new Span<uint>((void*)ptr1, 130);
108
+
109
+ var span2 = new Span<uint>((void*)ptr2, 130);
110
+
111
+ var ref_dat1_Data1 = Unsafe.AsRef<Data1>((void*)ptr1);
112
+
113
+ var ref_dat2_Data1 = Unsafe.AsRef<Data1>((void*)ptr2);
114
+
115
+ var ref_dat1_Data2 = Unsafe.AsRef<Data2>((void*)ptr1);
116
+
117
+ var ref_dat2_Data2 = Unsafe.AsRef<Data2>((void*)ptr2);
118
+
119
+
120
+
121
+ Console.ReadLine();
122
+
123
+ }
124
+
125
+ }
126
+
127
+ catch (Exception ex)
128
+
129
+ {
130
+
131
+ Console.Write(ex.ToString());
132
+
133
+ }
134
+
135
+ }
136
+
137
+ }
138
+
139
+ ```
140
+
141
+ デバッグ実行してConsole.ReadLineの辺りにブレークポイントを設定し、デバッグ⇒ウィンドウ⇒メモリでptr1,ptr2の指すメモリ内のデータの配置のされ方を覗いたり、変数の値を覗いたりしてみてください。
142
+
143
+ 何故上手くいかないのか理由が判ると思います。