プログラマのつれづれなるままにプログラマのつれづれなるままに音宮志久が思ったことなどをネタにします。プログラムネタ・数学ネタがメインです。Win32とWin64の関数呼び出しWin32とWin64の関数呼び出しコメントを残す差分パッチを作るときに、x64版を作ろうとしていろいろと四苦八苦しましたが・・・。気がつかれにくい話題ですが、はまった人がいるかな~と思って話題です。Win32には関数呼び出しの形式がVC++で実装すると、コンパイラの内部的に4つ存在します。引数を逆順でスタックに。引数を逆順にスタックに。引数を逆順にスタックに。thisポインタをecxレジスタに格納。引数を先頭二つをのぞいて逆順にスタックに。目をecxレジスタ、二番目をedxレジスタに。通常のコード実装ではcdeclかstdcallかどちらかを選択することになるので、関数ポインタを汎用的に管理するクラス(delegateなど)を自前で実装すると、両方とも(クラスも入れると3つとも)受け入れられるように実装することになります。ちなみに、クラスのメンバ関数でcdeclやstdcallを記述すると、スタックの先頭をthisポインタにして呼び出します。ところが、Win64ではCPUのレジスタ数が増えた(8個=>16個)ため、コンパイラが内部的にcdecl=stdcall(=fastcall)としてしまいます。ある程度の引数の個数ならスタックにPushしなくても、レジスタ渡しで十分だからですね。そのため、Win32用に、両方でコードを組んでいると、Win64でコンパイルしようとすると、オーバーロードが効かない、というよりは、同じ関数定義と勘違いされます。おかげでこんな実装が必要になっちゃいます。以下は私がライブラリで使用しているhandle_holderというテンプレートクラスです。不必要になると解放関数を呼び出して自動的にハンドルを解放するクラスです。!defined(_WIN32)#ifをつかって、コンパイル時に共通となる部分がオーバーロードしないように分けているわけですね・・・。いうのが必要になるのがかなり面倒なのですが・・・。コメントをキャンセルメールアドレスが公開されることはありません。志久プログラムネタや思いついたり世間で話題になっている数学ネタを解説したりしています。プログラマとしては今年度(つまり2020年3月)までの復帰となるか、完全復帰となるか、別の仕事に戻るかは運と実力次第。ちなみに教育系のプログラムでもOKです。アクセスカウンタアクセス数:スポンサーリンク。