回答編集履歴
6
(3) を取り消し
test
CHANGED
@@ -7,8 +7,8 @@
|
|
7
7
|
ref string で受けるなら、BSTR* を返さないといけないのでは?
|
8
8
|
BSTR は char* にキャストできますが、その逆はダメだと思います。
|
9
9
|
|
10
|
-
(3) 1回目の MallocEx1 で string オブジェクト(モドキ)が作成されます。
|
10
|
+
~~(3) 1回目の MallocEx1 で string オブジェクト(モドキ)が作成されます。~~
|
11
|
-
2回目の MallocEx1 では 別の string オブジェクトが作成され、str1 に格納されますが、1回目の string オブジェクトは参照が切れるので GC が動くと解放されてもおかしくありません。
|
11
|
+
~~2回目の MallocEx1 では 別の string オブジェクトが作成され、str1 に格納されますが、1回目の string オブジェクトは参照が切れるので GC が動くと解放されてもおかしくありません。~~
|
12
12
|
|
13
13
|
---
|
14
14
|
### うまくいった組み合わせ
|
5
MarshalAs で指定された型を追記
test
CHANGED
@@ -39,7 +39,7 @@
|
|
39
39
|
|
40
40
|
ref string で渡したとき C# の動きは次のようになっていると思われます。
|
41
41
|
|
42
|
-
(1) 文字列を渡すとき、null でなければ BSTR 文字列を作成し、そのアドレスを dll に渡す
|
42
|
+
(1) 文字列を渡すとき、null でなければ BSTR 文字列(MarshalAs で指定された型)を作成し、そのアドレスを dll に渡す
|
43
43
|
(2) DLL から戻ってきたら返された BSTR から String 文字列を作成し、渡された BSTR は解放する
|
44
44
|
|
45
45
|
こう考えると辻褄が合います。
|
4
考察を追加
test
CHANGED
@@ -34,4 +34,14 @@
|
|
34
34
|
}
|
35
35
|
```
|
36
36
|
|
37
|
+
---
|
38
|
+
### 考察
|
37
39
|
|
40
|
+
ref string で渡したとき C# の動きは次のようになっていると思われます。
|
41
|
+
|
42
|
+
(1) 文字列を渡すとき、null でなければ BSTR 文字列を作成し、そのアドレスを dll に渡す
|
43
|
+
(2) DLL から戻ってきたら返された BSTR から String 文字列を作成し、渡された BSTR は解放する
|
44
|
+
|
45
|
+
こう考えると辻褄が合います。
|
46
|
+
|
47
|
+
|
3
うまくいったパターンを追記
test
CHANGED
@@ -10,3 +10,28 @@
|
|
10
10
|
(3) 1回目の MallocEx1 で string オブジェクト(モドキ)が作成されます。
|
11
11
|
2回目の MallocEx1 では 別の string オブジェクトが作成され、str1 に格納されますが、1回目の string オブジェクトは参照が切れるので GC が動くと解放されてもおかしくありません。
|
12
12
|
|
13
|
+
---
|
14
|
+
### うまくいった組み合わせ
|
15
|
+
|
16
|
+
以下の組み合わせでメモリ破壊なく動きました。
|
17
|
+
|
18
|
+
|
19
|
+
```csharp
|
20
|
+
[DllImport("SampleDLL.Dll")]
|
21
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
22
|
+
extern public static string StringTest(
|
23
|
+
[MarshalAs(UnmanagedType.BStr)] ref string buff);
|
24
|
+
```
|
25
|
+
|
26
|
+
```c++
|
27
|
+
BSTR WINAPI StringTest(BSTR* ppRet) {
|
28
|
+
wchar_t str[] = L"Test!";
|
29
|
+
if (*ppRet != nullptr) {
|
30
|
+
SysFreeString(*ppRet);
|
31
|
+
}
|
32
|
+
*ppRet = SysAllocStringLen(str, lstrlen(str));
|
33
|
+
return SysAllocStringLen(str, lstrlen(str));
|
34
|
+
}
|
35
|
+
```
|
36
|
+
|
37
|
+
|
2
説明を少し変更
test
CHANGED
@@ -7,6 +7,6 @@
|
|
7
7
|
ref string で受けるなら、BSTR* を返さないといけないのでは?
|
8
8
|
BSTR は char* にキャストできますが、その逆はダメだと思います。
|
9
9
|
|
10
|
-
(3) 1回目の MallocEx1 で string オブジェクト(モドキ)が
|
10
|
+
(3) 1回目の MallocEx1 で string オブジェクト(モドキ)が作成されます。
|
11
|
-
2回目の MallocEx1 では 別の string オブジェクトが
|
11
|
+
2回目の MallocEx1 では 別の string オブジェクトが作成され、str1 に格納されますが、1回目の string オブジェクトは参照が切れるので GC が動くと解放されてもおかしくありません。
|
12
12
|
|
1
関数名間違い
test
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
(1) DLL の作りがおかしいです。
|
2
|
-
Malloc を2回呼び出すと、tmp は置き換わっちゃうのでは?
|
2
|
+
MallocEx を2回呼び出すと、tmp は置き換わっちゃうのでは?
|
3
3
|
1回目に呼び出したときに確保したメモリを解放できなくなっちゃいます。
|
4
4
|
FreeEx のほうはアドレスを渡して解放すべきです。
|
5
5
|
|