DOBON.NET DOBON.NETプログラミング掲示板過去ログ

APIを呼んだ後変数の値が変わる

環境/言語:[win2000SP4/XPSP2 VB.net2003]
分類:[.NET]

例えばInsertMenuで

Public Declare Function InsertMenu Lib "user32" Alias "InsertMenuA" (ByVal hMenu As Integer, ByVal uPosition As Integer, ByVal uFlags As Integer, ByVal uIDNewItem As Integer, ByVal lpNewItem As String) As Integer

Call InsertMenu(hPopupMenu, MnuItmCnt, MF_BYCOMMAND, MnuItmCnt, ItmAry_Name)

とやるとこの呼出から戻った後ItmAry_Nameの内容が壊れています
(全角文字列の2文字目以降が化ける)
ByValなのに何故?と思うのですが…
ちなみにInsertMenu自体はちゃんと成功しています
■No22546に返信(/400さんの記事)
> とやるとこの呼出から戻った後ItmAry_Nameの内容が壊れています
> (全角文字列の2文字目以降が化ける)
> ByValなのに何故?と思うのですが…
> ちなみにInsertMenu自体はちゃんと成功しています

  回答ではありません!

  ByVal だから・・・と言う固定観念では、解決しませんヨ!

  http://www.pinvoke.net/default.aspx/user32/InsertMenu.html

  まず、その変数のAPIの宣言は、『LPTSTR』ですから、アドレス
  渡しですネ!(ポインタが渡る)
  で、それを.NET側で宣言する場合は、ByValで宣言するのですが。

  後、壊れる理由は、これだけの内容では解りません・・・

以上。
昔、調査した内容ですが、以下の事例と同じ現象でしょうね。
http://www5b.biglobe.ne.jp/~yone-ken/VBNET/Reference/ref2_GetPrivateProfileString.html

マーシャリングの仕方に何か問題があるか、.NET FrameworkまたはVBのコンパイラの不具合、
もしくは、その両方の問題だろうと思います。

ただ実際のところは、P/Invokeが.NETの中でどのように処理されるのかの
詳しいところはわからないのではっきりとした原因はわかりません。

■No22546に返信(/400さんの記事)
> 例えばInsertMenuで
>
> Public Declare Function InsertMenu Lib "user32" Alias "InsertMenuA" (ByVal hMenu As Integer, ByVal uPosition As Integer, ByVal uFlags As Integer, ByVal uIDNewItem As Integer, ByVal lpNewItem As String) As Integer
>
> Call InsertMenu(hPopupMenu, MnuItmCnt, MF_BYCOMMAND, MnuItmCnt, ItmAry_Name)
>
> とやるとこの呼出から戻った後ItmAry_Nameの内容が壊れています
> (全角文字列の2文字目以降が化ける)
> ByValなのに何故?と思うのですが…

以下のように変更してみるとどうでしょうか。

ByVal lpNewItem As String
↓ 変更
<MarshalAs(UnmanagedType.LPTStr)> ByVal lpNewItem As String
(この変更のためにはファイルの先頭に
Imports System.Runtime.InteropServices
が必要です)
レスありがとうございます

■No22548に返信(よねKENさんの記事)
> 昔、調査した内容ですが、以下の事例と同じ現象でしょうね。
> http://www5b.biglobe.ne.jp/~yone-ken/VBNET/Reference/ref2_GetPrivateProfileString.html
>
> マーシャリングの仕方に何か問題があるか、.NET FrameworkまたはVBのコンパイラの不具合、
> もしくは、その両方の問題だろうと思います。
>
> ただ実際のところは、P/Invokeが.NETの中でどのように処理されるのかの
> 詳しいところはわからないのではっきりとした原因はわかりません。
>
> ■No22546に返信(/400さんの記事)
>>例えばInsertMenuで
>>
>>Public Declare Function InsertMenu Lib "user32" Alias "InsertMenuA" (ByVal hMenu As Integer, ByVal uPosition As Integer, ByVal uFlags As Integer, ByVal uIDNewItem As Integer, ByVal lpNewItem As String) As Integer
>>
>>Call InsertMenu(hPopupMenu, MnuItmCnt, MF_BYCOMMAND, MnuItmCnt, ItmAry_Name)
>>
>>とやるとこの呼出から戻った後ItmAry_Nameの内容が壊れています
>>(全角文字列の2文字目以降が化ける)
>>ByValなのに何故?と思うのですが…
>
> 以下のように変更してみるとどうでしょうか。
>
> ByVal lpNewItem As String
> ↓ 変更
> <MarshalAs(UnmanagedType.LPTStr)> ByVal lpNewItem As String
> (この変更のためにはファイルの先頭に
> Imports System.Runtime.InteropServices
> が必要です)

これでやってみたらちゃんと動きました
MarshalAsでググってストリングそのまま渡しちゃいけないんだってことに
今更気づいたり…
もう少しP/INVOKE勉強します
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板