(AHK)(AutoHotkey)(API関数で固定長変数に文字列を投げ込んだ時 正しく値が得られない〜(泣)編)
今回は ちょっとしたTipです
流行らせるページにも 書いてありますが 結構見落としがちな所ですし
ここにハマると API関数が失敗しているのか成功しているのかすら疑心暗鬼になって
諦めてしまう事がよくあるんですよね、 私も 最初 この件で 折れそうになった 笑)
解決方法は 実は結構 簡単なもので
これは おそらく AHKの管轄外で 変数の中身が変更された場合 AHKの持っている情報とずれが生じてしまい
文字列として 正しく データ型を変換できていないのが 原因なんでしょうね
DllCallで 書き戻される対象の固定長変数を "Str" で指示した場合は
VarSetCapacity(<固定長変数名>, -1) をしなくても 正しく読み込めますよね
これは おそらく AHKが 面倒を見てくれているんでしょう
そして 書き戻される対象の固定長変数を "UInt" として アドレスで指定した場合は
VarSetCapacity(<固定長変数名>, -1) をしないと 正しく読み込めないみたいです
ここら辺を知るとこれまで 解決できなかった所が 色々と解決できるかもしれませんよ? 笑)
もちろん 本件のような時には こういうことも 考える必要があります
『API関数が 対象の固定長変数に 想定したとおりに書き込んだのか?』
ということですね
想定した通りに書き込まれていなければ
いくら VarSetCapacity(<固定長変数名>, -1) を したってダメってことですね
そんな時は 悩むよりも先に 変数の内容を ダンプしてチェックした方が楽ですね
流行らせるページにも 書いてありますが 結構見落としがちな所ですし
ここにハマると API関数が失敗しているのか成功しているのかすら疑心暗鬼になって
諦めてしまう事がよくあるんですよね、 私も 最初 この件で 折れそうになった 笑)
解決方法は 実は結構 簡単なもので
VarSetCapacity(<固定長変数名>, -1)と やって AHKに変数の内容を再チェックさせる事なんですね
これは おそらく AHKの管轄外で 変数の中身が変更された場合 AHKの持っている情報とずれが生じてしまい
文字列として 正しく データ型を変換できていないのが 原因なんでしょうね
DllCallで 書き戻される対象の固定長変数を "Str" で指示した場合は
VarSetCapacity(<固定長変数名>, -1) をしなくても 正しく読み込めますよね
これは おそらく AHKが 面倒を見てくれているんでしょう
そして 書き戻される対象の固定長変数を "UInt" として アドレスで指定した場合は
VarSetCapacity(<固定長変数名>, -1) をしないと 正しく読み込めないみたいです
ここら辺を知るとこれまで 解決できなかった所が 色々と解決できるかもしれませんよ? 笑)
VarSetCapacity(buf_A, 30, 0x00) VarSetCapacity(buf_B, 30, 0x00) buf_A := "秋山澪!!" ; buf_A の値を buf_B に 書き込む API関数、 アドレスを+4しているので「澪!!」がコピーされる DllCall("kernel32.dll\lstrcpyA", "UInt", &buf_B, "UInt", &buf_A + 4, "UInt") ; 虚しくも メッセージボックスには 何も表示されない・・・、文字列としても扱えない・・・ MsgBox,% buf_B ; おまじないの言葉を唱えると VarSetCapacity(buf_B, -1) ; メッセージボックスには 「澪!!」の文字が!!、文字列としても扱える! MsgBox,% buf_B
もちろん 本件のような時には こういうことも 考える必要があります
『API関数が 対象の固定長変数に 想定したとおりに書き込んだのか?』
ということですね
想定した通りに書き込まれていなければ
いくら VarSetCapacity(<固定長変数名>, -1) を したってダメってことですね
そんな時は 悩むよりも先に 変数の内容を ダンプしてチェックした方が楽ですね
;------------------------------------------------------------------------------------------------------------------------------------ ; 指定されたアドレスから サイズ分のデータを ファイルに書き出します DumpMem(OutPutFileName, pBufferAddress, Size) { If !( hFile := DllCall("kernel32.dll\CreateFile", "Str", OutPutFileName, "UInt", 0x40000000, "UInt", 0, "UInt", 0, "UInt", 0x2, "UInt", 0x80, "UInt", 0, "UInt") ) Return 0 Result := DllCall("kernel32.dll\WriteFile", "UInt", hFile, "UInt", pBufferAddress, "UInt", Size, "UIntP", WritedSize, "UInt", 0, "Int") DllCall("kernel32.dll\CloseHandle", "UInt", hFile, "Int") If Result Return 1 Else Return 0 } ;------------------------------------------------------------------------------------------------------------------------------------もし buf_A という 30バイトのサイズの 固定長変数の内容を知りたい場合は
DumpMem("____dump.bin", &buf_A, 30)とやれば buf_Aの内容を ____dump.binというファイルに ダンプ出来ます