回答編集履歴

6

(3) を取り消し

2023/09/24 02:22

投稿

KOZ6.0
KOZ6.0

スコア2696

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 で指定された型を追記

2023/09/23 23:56

投稿

KOZ6.0
KOZ6.0

スコア2696

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

考察を追加

2023/09/23 23:00

投稿

KOZ6.0
KOZ6.0

スコア2696

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

うまくいったパターンを追記

2023/09/23 22:33

投稿

KOZ6.0
KOZ6.0

スコア2696

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

説明を少し変更

2023/09/23 06:51

投稿

KOZ6.0
KOZ6.0

スコア2696

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 オブジェクトが出来るので、1回目の string オブジェクトは GC が動くと解放されてもおかしくありません。
11
+ 2回目の MallocEx1 では 別の string オブジェクトが作成されstr1 に格納されますが、1回目の string オブジェクトは参照が切れるので GC が動くと解放されてもおかしくありません。
12
12
 

1

関数名間違い

2023/09/23 04:54

投稿

KOZ6.0
KOZ6.0

スコア2696

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