teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

修正

2020/11/04 05:28

投稿

退会済みユーザー
answer CHANGED
@@ -13,6 +13,8 @@
13
13
  [Blittable 型と非 Blittable 型](https://docs.microsoft.com/ja-jp/dotnet/framework/interop/blittable-and-non-blittable-types)
14
14
  Marshalクラスや、PInvoke呼び出しを経由する分には、マーシャリングで上手く変換してくれるのですが、非Blittableな構造体の実際のメモリの配置のされ方は、C言語の構造体とは違います。
15
15
 
16
+ 下記のコードをデバッグ実行して、Console.ReadLineの辺りにブレークポイントを設定し、デバッグ⇒ウィンドウ⇒メモリでptr1,ptr2の指すメモリ内のデータの配置のされ方を覗いたり、変数の値を覗いたりしてみてください。
17
+ 何故上手くいかないのか理由が判ると思います。
16
18
  ```csharp
17
19
  class Program
18
20
  {
@@ -67,6 +69,4 @@
67
69
  }
68
70
  }
69
71
  }
70
- ```
72
+ ```
71
- デバッグ実行してConsole.ReadLineの辺りにブレークポイントを設定し、デバッグ⇒ウィンドウ⇒メモリでptr1,ptr2の指すメモリ内のデータの配置のされ方を覗いたり、変数の値を覗いたりしてみてください。
72
- 何故上手くいかないのか理由が判ると思います。

1

追記

2020/11/04 05:28

投稿

退会済みユーザー
answer CHANGED
@@ -7,4 +7,66 @@
7
7
  public uint member2;
8
8
  public fixed uint member3[128];
9
9
  };
10
- ```
10
+ ```
11
+
12
+ 固定ではない配列を含む構造体は、非Blittable型になります。
13
+ [Blittable 型と非 Blittable 型](https://docs.microsoft.com/ja-jp/dotnet/framework/interop/blittable-and-non-blittable-types)
14
+ Marshalクラスや、PInvoke呼び出しを経由する分には、マーシャリングで上手く変換してくれるのですが、非Blittableな構造体の実際のメモリの配置のされ方は、C言語の構造体とは違います。
15
+
16
+ ```csharp
17
+ class Program
18
+ {
19
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
20
+ public unsafe struct Data1
21
+ {
22
+ public uint member1;
23
+ public uint member2;
24
+ public fixed uint member3[128];
25
+ };
26
+
27
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
28
+ public struct Data2
29
+ {
30
+ public uint member1;
31
+ public uint member2;
32
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
33
+ public uint[] member3;
34
+ };
35
+
36
+ static void Main(string[] args)
37
+ {
38
+ try
39
+ {
40
+ unsafe
41
+ {
42
+ var dat1 = new Data1();
43
+ dat1.member1 = 1;
44
+ dat1.member2 = 2;
45
+ for (uint i = 0; i < 128; i++)
46
+ {
47
+ dat1.member3[i] = i;
48
+ }
49
+
50
+ var ptr1 = &dat1;
51
+ var dat2 = Marshal.PtrToStructure<Data2>((IntPtr)ptr1);
52
+ //var ptr2 = &dat2; //これはコンパイルエラー
53
+ var ptr2 = Unsafe.AsPointer(ref dat2);
54
+ var span1 = new Span<uint>((void*)ptr1, 130);
55
+ var span2 = new Span<uint>((void*)ptr2, 130);
56
+ var ref_dat1_Data1 = Unsafe.AsRef<Data1>((void*)ptr1);
57
+ var ref_dat2_Data1 = Unsafe.AsRef<Data1>((void*)ptr2);
58
+ var ref_dat1_Data2 = Unsafe.AsRef<Data2>((void*)ptr1);
59
+ var ref_dat2_Data2 = Unsafe.AsRef<Data2>((void*)ptr2);
60
+
61
+ Console.ReadLine();
62
+ }
63
+ }
64
+ catch (Exception ex)
65
+ {
66
+ Console.Write(ex.ToString());
67
+ }
68
+ }
69
+ }
70
+ ```
71
+ デバッグ実行してConsole.ReadLineの辺りにブレークポイントを設定し、デバッグ⇒ウィンドウ⇒メモリでptr1,ptr2の指すメモリ内のデータの配置のされ方を覗いたり、変数の値を覗いたりしてみてください。
72
+ 何故上手くいかないのか理由が判ると思います。