stdcall_thunk

昨日のクラス名が長すぎる問題ですが、早速
direct_sound_buffer → direct_sound_sink
direct_sound_capture_buffer → direct_sound_source
に変更しました。
これで、vc8ideディレクトリ配下以外は、inspectに引っかからなくなりました。
vc8ideディレクトリにはWin32 GUI Genericsを使ったサンプルが入っているのですが、この際フルスクラッチのコードと置き換えようかと思います。


Win32でGUIフレームワークを使わずに済ます場合、どうしても__stdcall呼び出し用のthunkが欲しくなります。
そこで、以前作成したcdecl_thunkと同じインタフェースでstdcall_thunkも作ってみました。
<hamigaki/detail/i386/stdcall_thunk.hpp>
__cdeclの場合は、引数をスタックに積み直していましたが、__stdcallの場合は関数側でスタックの後始末をしてくれるので、スタックのトップを書き換えてjmpするだけで済みます。


以下、サンプルコードです。

#include <hamigaki/detail/stdcall_thunk.hpp>
#include <hamigaki/detail/virtual_memory.hpp>
#include <iostream>

class hoge
{
public:
    void foo(long a, long b)
    {
        std::cout
            << "this=" << static_cast<void*>(this)
            << ", a=" << a
            << ", b=" << b
            << std::endl;
    }

    static void stdcall_helper(hoge* this_ptr, long a, long b)
    {
        this_ptr->foo(a, b);
    }
};

typedef void (*func_type)(long, long);

int main()
{
    hoge h;
    h.foo(1,2); // 通常の呼び出し

    // 仮想メモリの準備
    using namespace hamigaki::detail;
    virtual_memory buffer(sizeof(stdcall_thunk));
    stdcall_thunk* thunk_ptr = static_cast<stdcall_thunk*>(buffer.address());

    // アドレスの設定
    thunk_ptr->set_instance(func_ptr_cast<void*>(&hoge::stdcall_helper), &h);

    // 命令キャッシュのクリアとメモリ保護設定
    buffer.flush_icache();
    buffer.protect(virtual_memory::execute|virtual_memory::read);

    func_type func_ptr;
    thunk_ptr->copy_address(func_ptr);
    (*func_ptr)(1,2); // サンク経由の呼び出し
}