[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: C++ template function idiom
- From: "Wesley Smith" <wesley.hoke@...>
- Date: Mon, 5 Mar 2007 02:26:09 -0800
I'm wondering if anyone else has tried this before. I've come up with
a way to wrap a class of functions based on function signature using
templates and lua closures that doesn't hit performance that much,
saves a ton of repetitive coding and avoids excessive macros.
Basically, I've created an array of structs that hold a function
pointer, the name of the function, and some extra data specific to
this library. I push a closure with an index into the array of
structs and the generic function. When the generic function gets
called, the upvalue indexes into the array and gets the appropriate
function and data.
template <class T>
class udata
{
typedef const dReal * (*vecGetter)(T);
typedef void (*vecPointGetter)(T, dReal px, dReal py, dReal pz,
dVector3 result);
template<typename F>
struct odeFunctor {
const char *name;
F func;
char size;
};
static const odeFunctor<vecGetter> ode_udata_vecGetter[];
static const odeFunctor<vecPointGetter> ode_udata_vecPointGetter[];
//lots of other stuff
};
#define functor_entry(func, size) {#func, func, size}
//example use
template <>
udata<dBodyID>::odeFunctor<udata<dBodyID>::vecGetter> const
udata<dBodyID>::ode_udata_vecGetter[] =
{
functor_entry(dBodyGetPosition, 3),
functor_entry(dBodyGetLinearVel, 3),
functor_entry(dBodyGetAngularVel, 3),
functor_entry(dBodyGetForce, 3),
functor_entry(dBodyGetTorque, 3),
{NULL, NULL}
};
template <class T>
int udata<T> :: udata_genericGetter(lua_State *L)
{
T o;
const dReal *param;
int index = lua_tointeger(L, lua_upvalueindex(1));
if(!lua_isuserdata(L, 1))
luaL_error(L, " argument 1 for %s must be a %s",
udata<T>::ode_udata_vecGetter[index].name, name);
o = udata<T>::to_udata(L, 1);
param = udata<T>::ode_udata_vecGetter[index].func(o);
lua_newtable(L);
for(int i=0; i < udata<T>::ode_udata_vecGetter[index].size; i++)
{
lua_pushnumber(L, param[i]);
lua_rawseti(L, -2, i+1);
}
return 1;
}
//example Lua init with lib table on top of stack
int i=0;
while(udata<T>::ode_udata_vecGetter[i].name)
{
lua_pushstring(L, udata<T>::ode_udata_vecGetter[i].name);
lua_pushinteger(L, i);
lua_pushcclosure(L, udata<T>::udata_genericGetter, 1);
lua_settable(L, -3);
i++;
}