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:

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.

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:

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<typenameT>structis_int{enum{value=false};};template<>structis_int<int>{enum{value=true};};template<>structis_int<short>{enum{value=true};};template<>structis_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:

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.