Regarding function pointer arrays, I'm doing something in labrea (<a href="http://github.com/dustin/labrea" rel="nofollow">http://github.com/dustin/labrea</a>) where I need to make what is effectively an FFI call from C to C where I know the number of arguments, and their types, but I have them in the form of an array of unions.<p>For example, if I need to call read, it's basically an invocation of a function with a 4 byte, 8 byte, and then 4 byte argument (on a 64-bit system). I have a union argument type that represents 32-bit and 64-bit parameter types at the same time. I make a call like this:<p><pre><code> rv = abstractInvoke(&fun, args);
</code></pre>
which, depending on arity of fun, invokes something like this (auto-generated):<p><pre><code> rv = abstractInvoke(fun, args[0], args[1], args[2]);
</code></pre>
That three-arg function looks roughly like this (calling my argument type ``a_t'' to abbreviate):<p><pre><code> a_t abstractInvoke(struct ftype *fun, a_t a0, a_t a1, a_t a2) {
static a_t (*allfuns[])(const void*, a_t a0, a_t a1, a_t a2) = {
invoke_3_4_444, // 0
invoke_3_8_444, // 1
invoke_3_4_448, // 2
invoke_3_8_448, // 3
invoke_3_4_484, // 4
invoke_3_8_484, // 5
// [...]
invoke_3_8_888, // 15
};
return allfuns[fun->offset](fun->orig, a0, a1, a2);
}
</code></pre>
I generate all of the functions by arity and types and then compute an array offset of them ahead of time (so read has an offset of 5 since it returns an 8 byte value and its arguments take a 4 byte, 8 byte, and then 4 byte value).<p>Without this trick, I'd have to use very non-portable assembler to do the same invocation (OK, I'd use libffi or dyncall's already prepackaged very non-portable assembler, which I may end up with anyway) to make this function call.