Ghetto Closures in C++ III: Templates and Traits and Interfaces, oh my!
Last time, we went over generating a tiny ASM thunk that could wrap a C++ method pointer (instance plus function) up
in a non-method __stdcall function pointer, suitable for use as, say, a win32 WndProc.  Next, I’m going to talk about
wrapping it all up in a convenient API. To do this, we’re going to need some template-fu.
Since I am using a modern compiler, I am going to see how close I can get to boost.function‘s interface:
boost::function<void ()> fn = &someFunction;
I consider this interface to be pretty rad.
boost::function works with only a single template argument, so we could go that route too. We could also accept that we’re doing something a bit different, and add a second parameter:
Thunk<LRESULT (Window::*)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)> wndProcThunk;
or
Thunk<Window, LRESULT (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)> wndProcThunk;
I picked the first one, mostly because it was the first thing that popped into my head. Here is my test harness:
#include <cstdio>
using std::printf;
struct I {
    virtual void print() = 0;
    virtual void printSum(double y) = 0;
};
struct C : I {
    C(int x)
        : x(x)
    { }
    void print() {
        printf("My x is %in", x);
    }
    void printSum(double y) {
        printf("%i + %f = %fn", x, y, x + y);
    }
    int x;
};
void main() {
    C instance(4);
    Thunk<void (I::*)()> thunk(&instance, &I::print);
    printf("n");
    thunk.get()();
    Thunk<void (I::*)(double)> thunk2(&instance, &I::printSum);
    printf("n");
    thunk2.get()(3.14);
}
First, I extracted the part of the code that actually constructs and cleans up the generated code. Everything else I’ll outline will just be scaffolding so that the interface is prettier.
template <typename D, typename S>
D really_reinterpret_cast(S s) {
    char __static_assert_that_types_have_same_size[sizeof(S) == sizeof(D)];
    union {
        S s;
        D d;
    } u;
    u.s = s;
    return u.d;
}
template <typename C, typename M>
void* createThunk(C* instance, M method) {
    char code[] = {
        0xB9, 0, 0, 0, 0,   // mov ecx, 0
        0xB8, 0, 0, 0, 0,   // mov eax, 0
        0xFF, 0xE0          // jmp eax
    };
    // YEEHAW
    *((I**)(code + 1)) = instance;
    *((void**)(code + 6)) = really_reinterpret_cast<void*>(method);
    void* thunk = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(thunk, &code, sizeof(code));
    FlushInstructionCache(GetCurrentProcess(), thunk, sizeof(code));
    return thunk;
}
void releaseThunk(void* thunk) {
    VirtualFree(thunk, 0, MEM_RELEASE);
}
To be honest, this interface isn’t all that bad: all you have to do is remember to manage the lifetime of the generated code and cast the void* you get to the right type. That’s kind of boring, though, so let’s instead see if we can make something kickass and typesafe.
I like objects, so let’s start with one of those.
template <typename M>
struct Thunk {
    typedef M Method;
    typedef typename methodptr_traits<M>::class_type Class;
    typedef typename methodptr_traits<M>::function_type Function;
    Thunk(Class* instance, Method method)
        : ptr(createThunk(instance, method))
    { }
    ~Thunk() {
        releaseThunk(ptr);
    }
    Function get() const {
        return reinterpret_cast<Function>(ptr);
    }
private:
    Thunk(const Thunk&);
    void* ptr;
};
This is simple enough to be boring, except for this methodptr_traits thing.
methodptr_traits is an instance of something called a traits class. Basically, it is a fancy template type that defines various other types. You can think of it as a way to code ad-hoc, compile-time type introspection.
If you’ve never used templates this way, the implementation is pretty intimidating:
template <typename F>
struct methodptr_traits;
template <typename ReturnType, typename T>
struct methodptr_traits<ReturnType (T::*)()> {
    typedef T class_type;
    typedef ReturnType (__stdcall *function_type)();
};
This is one of the more convoluted things one can do with templates, and I’ll be the first to admit that I think it’s a bit scary. Let’s rewind a bit and look at this in simpler terms. Say we want a boolean variable that’s true if a particular template type is a number. We can use template specialization to accomplish this pretty easily:
template <typename T> struct is_int { enum {value = false}; };
template <> struct is_int<int> { enum {value = true}; };
template <> struct is_int<short> { enum {value = true}; };
template <> struct is_int<char> { enum {value = true}; };
// and so on
I might leverage this code with something like the following:
if (is_int<T>::value) { /* stuff */ }
and be off to the races.
Cool, right? Now what if we instead wanted to know whether something is a std::vector, whatever the element type? The same principle applies, but now we have a template specialization that is itself a template:
template <typename T> struct is_vector { enum {value=false}; };
template <typename E> struct is_vector<std::vector<E> > { enum {value=true}; };
How to use this should be obvious:
if (is_vector<T>::value) { /* do something that only works on std::vector */ }
methodptr_traits is just a tiny jump further. Most of the terror that this sort of thing inspires is really the fault of C++’s ridiculous function pointer syntax.
It is kind of a drag that C++ templates cannot express functions without specifying exactly how many arguments the function has. Because of this, a new specialization must be written for each argument count you want to support. I only did 0 and 1 arguments because this is just a small example. boost tends to support a minimum of 10 arguments by default, which is good enough for almost everyone.
For this example, I only need 0 and 1 argument, so here’s the specialization for a one-argument function:
template <typename ReturnType, typename T, typename Arg1>
struct methodptr_traits<ReturnType (T::*)(Arg1)> {
    typedef T class_type;
    typedef ReturnType (__stdcall *function_type)(Arg1);
};
And that’s it! With a single templatized class, we can dynamically generate an assembly thunk that works as a perfectly usable __stdcall function. We can pass this function pointer on to Win32, GLU, or whatever other C library we might need a callback function for.