回答編集履歴

1

追記

2017/11/29 01:52

投稿

Chironian
Chironian

スコア23272

test CHANGED
@@ -33,3 +33,133 @@
33
33
  handle.Free();
34
34
 
35
35
  ```
36
+
37
+
38
+
39
+ ---
40
+
41
+ 【追加のご報告を見て構造体の振る舞いが気になったので確認してみました】
42
+
43
+ C#の構造体をほとんど使ったことが無かったので、`Info info;`で領域獲得されるかと思っていたのですが、そうではないようですね。直後の`Marshal.StructureToPtr(info, ptr, false);`で「CS0165 未割り当てのローカル変数 'info' が使用されました」エラーになりました。
44
+
45
+
46
+
47
+ その他、私のミスも含めて修正してみたところ、どちらも 2 が表示されました。
48
+
49
+ 元々のm_Ptr は AllocCoTaskMem で獲得した領域へ StructureToPtr にてm_Infoをコピーしたものですので、m_Ptr は m_Info を指していません。
50
+
51
+
52
+
53
+ ```C#
54
+
55
+ public class ClassInfo
56
+
57
+ {
58
+
59
+ [Serializable]
60
+
61
+ public struct Info
62
+
63
+ {
64
+
65
+ public int state;
66
+
67
+ }
68
+
69
+
70
+
71
+ public Info m_Info;
72
+
73
+
74
+
75
+ public IntPtr m_Ptr;
76
+
77
+ public int m_Size;
78
+
79
+
80
+
81
+ public ClassInfo()
82
+
83
+ {
84
+
85
+ // stateを1に変更する
86
+
87
+ m_Info.state = 1;
88
+
89
+
90
+
91
+ // 構造体からポインターを取得する
92
+
93
+ m_Size = Marshal.SizeOf(typeof(Info));
94
+
95
+ m_Ptr = Marshal.AllocCoTaskMem(m_Size);
96
+
97
+ Marshal.StructureToPtr(m_Info, m_Ptr, false);
98
+
99
+ }
100
+
101
+
102
+
103
+ public void Update()
104
+
105
+ {
106
+
107
+ // stateを変更する
108
+
109
+ m_Info.state++;
110
+
111
+ #if true
112
+
113
+ // ポインターから復元する
114
+
115
+ IntPtr ptr = Marshal.AllocHGlobal(m_Size);
116
+
117
+ Marshal.StructureToPtr(m_Info, ptr, false);
118
+
119
+
120
+
121
+ // ここで上記で復元したinfo.stateが++されて2になった状態で取得したい
122
+
123
+ Info info = (Info)Marshal.PtrToStructure(ptr, typeof(Info));
124
+
125
+ Debug.WriteLine(info.state);
126
+
127
+
128
+
129
+ // 解放しておく
130
+
131
+ Marshal.FreeCoTaskMem(m_Ptr);
132
+
133
+ Marshal.FreeCoTaskMem(ptr);
134
+
135
+ #else
136
+
137
+ // ポインターから復元する
138
+
139
+ GCHandle handle = GCHandle.Alloc(m_Info, GCHandleType.Pinned);
140
+
141
+ IntPtr ptr = handle.AddrOfPinnedObject();
142
+
143
+
144
+
145
+ // ここで上記で復元したinfo.stateが++されて2になった状態で取得したい
146
+
147
+ Info info = (Info)Marshal.PtrToStructure(ptr, typeof(Info));
148
+
149
+ Debug.WriteLine(info.state);
150
+
151
+
152
+
153
+ // 解放しておく
154
+
155
+ handle.Free();
156
+
157
+ #endif
158
+
159
+ }
160
+
161
+ ```
162
+
163
+
164
+
165
+ Visual Studio 2017 Communityで確認しました。