LuaTinker的作者是Kwon-il Lee韩国人写的,最新的版本是0.2.C,这个C++ wrapper For Lua能够方便和
快捷与C/C++通信,LuaTinker参考了luabind和luaplus的特征写的,虽然没有bindlua和luaplus这本强大
和提供很多功能,LuaTinker的实现只有两个文件,但是LuaTinker提供的基本能够满足大部的要求,用户
还可以对它进一步的扩充,而且用于游戏上特为方便,以下是LuaTinker使用C++结构和类的例子:
// 一个基类
struct base
{
base() {}
const char* is_base(){ return "this is base"; }
};
// 一个测试类
class test : public base
{
public:
test(int val) : _test(val) {}
~test() {}
const char* is_test(){ return "this is test"; }
void ret_void() {}
int ret_int() { return _test; }
int ret_mul(int m) const { return _test * m; }
A get() { return A(_test); }
void set(A a) { _test = a.value; }
int _test;
};
int main()
{
// 注册base类型到LUA
lua_tinker::class_<base>("base")
.def("is_base", &base::is_base)
;
// 注册test类型到LUA,注册test的成员函数和成员变量
lua_tinker::class_<test>("test")
.inh<base>() // 注册继承类
.def(lua_tinker::constructor<int>()) //注册构造函数
.def("is_test", &test::is_test) // 注册成员函数
.def("ret_void", &test::ret_void)
.def("ret_int", &test::ret_int)
.def("ret_mul", &test::ret_mul)
.def("get", &test::get)
.def("set", &test::set)
.def_readwrite("_test", &test::_test) // 注册成员变量
;
test g_test(11);
lua_tinker::decl("g_test", &g_test);
}
// Lua脚本
temp = test(4) 创建一个test类
print(temp._test) 打印test的_test成员
print(g_test)
print(g_test._test) 打印g_test的成员变量_test
print(g_test:is_test()) 输出信息
print(g_test:ret_int()) 返回g_test的成员变量_test
这么几句就能够方便的使用C/C++定义的结构或类,下一篇将会介绍其他的用法.
介绍完用法之后会从结构上分析lua_tinker的结构和设计.
// lua_tinker.h
//
// LuaTinker - Simple and light C++ wrapper for Lua.
//
// Copyright (c) 2005 Kwon-il Lee ([email protected])
//
// please check Licence.txt file for licence and legal issues.
#if !defined(_LUA_TINKER_H_)
#define _LUA_TINKER_H_
#include <new>
namespace lua_tinker
{
// debug helpers
void enum_stack(lua_State *L, int start=0);
int _exception(lua_State *L);
void dofile(const char *filename);
void dostring(const char* buff);
void dobuffer(const char* buff, size_t sz);
void dofile(lua_State *L, const char *filename);
void dostring(lua_State *L, const char* buff);
void dobuffer(lua_State *L, const char* buff, size_t sz);
// basic Object
struct lua_state
{
static void open(lua_State *in)
{
L(in);
init_s64(in);
init_u64(in);
}
static lua_State* L(lua_State *in=NULL);
static void init_s64(lua_State *L);
static void init_u64(lua_State *L);
};
// for LuaBind
struct luabind : lua_state
{
};
struct lua_obj
{
lua_obj& operator,(const lua_obj& obj) { return *this; }
};
struct module
{
module(lua_State *L){}
void operator[](const lua_obj& obj){}
};
struct lua_value
{
virtual void to_lua(lua_State *L) = 0;
};
// type trait
template<typename T> struct class_;
template<bool C, typename A, typename B>
struct if_ {};
template<typename A, typename B>
struct if_<true, A, B> { typedef A type; };
template<typename A, typename B>
struct if_<false, A, B> { typedef B type; };
template<typename A>
struct is_ptr { static const bool value = false; };
template<typename A>
struct is_ptr<A*> { static const bool value = true; };
template<typename A>
struct is_ref { static const bool value = false; };
template<typename A>
struct is_ref<A&> { static const bool value = true; };
template<typename A>
struct remove_const { typedef A type; };
template<typename A>
struct remove_const<const A> { typedef A type; };
template<typename A>
struct base_type { typedef A type; };
template<typename A>
struct base_type<A*> { typedef A type; };
template<typename A>
struct base_type<A&> { typedef A type; };
template<typename A>
struct class_type { typedef typename remove_const<typename base_type<A>::type>::type type; };
/////////////////////////////////
enum { no = 1, yes = 2 };
typedef char (& no_type )[no];
typedef char (& yes_type)[yes];
struct int_conv_type { int_conv_type(int); };
no_type int_conv_tester (...);
yes_type int_conv_tester (int_conv_type);
no_type vfnd_ptr_tester (const volatile char *);
no_type vfnd_ptr_tester (const volatile short *);
no_type vfnd_ptr_tester (const volatile int *);
no_type vfnd_ptr_tester (const volatile long *);
no_type vfnd_ptr_tester (const volatile double *);
no_type vfnd_ptr_tester (const volatile float *);
no_type vfnd_ptr_tester (const volatile bool *);
yes_type vfnd_ptr_tester (const volatile void *);
template <typename T> T* add_ptr(T&);
template <bool C> struct bool_to_yesno { typedef no_type type; };
template <> struct bool_to_yesno<true> { typedef yes_type type; };
template <typename T>
struct is_enum
{
static T arg;
static const bool value = ( (sizeof(int_conv_tester(arg)) == sizeof(yes_type)) && (sizeof(vfnd_ptr_tester(add_ptr(arg))) == sizeof(yes_type)) );
};
/////////////////////////////////
// from lua
template<typename T>
struct void2val { static T invoke(void* input){ return *(T*)input; } };
template<typename T>
struct void2ptr { static T* invoke(void* input){ return (T*)input; } };
template<typename T>
struct void2ref { static T& invoke(void* input){ return *(T*)input; } };
template<typename T>
struct void2type
{
static T invoke(void* ptr)
{
return if_<is_ptr<T>::value
,void2ptr<base_type<T>::type>
,if_<is_ref<T>::value
,void2ref<base_type<T>::type>
,void2val<base_type<T>::type>
>::type
>::type::invoke(ptr);
}
};
template<typename T>
struct user2type { static T invoke(lua_State *L, int index) { return void2type<T>::invoke(lua_touserdata(L, index)); } };
template<typename T>
struct lua2enum { static T invoke(lua_State *L, int index) { return (T)(int)lua_tonumber(L, index); } };
template<typename T>
struct lua2object
{
static T invoke(lua_State *L, int index)
{
if(!lua_isuserdata(L,index))
{
lua_pushstring(L, "no class at first argument. (forgot ':' expression ?)");
lua_error(L);
}
return void2type<T>::invoke(user2type<user*>::invoke(L,index)->m_p);
}
};
template<typename T>
struct lua2type
{
static T invoke(lua_State *L, int index)
{
return if_<is_enum<T>::value
,lua2enum<T>
,lua2object<T>
>::type::invoke(L, index);
}
};
struct user
{
user(void* p) : m_p(p) {}
virtual ~user() {}
void* m_p;
};
template<typename T>
struct val2user : user
{
val2user() : user(new T) {}
template<typename T1>
val2user(T1 t1) : user(new T(t1)) {}
template<typename T1, typename T2>
val2user(T1 t1, T2 t2) : user(new T(t1, t2)) {}
template<typename T1, typename T2, typename T3>
val2user(T1 t1, T2 t2, T3 t3) : user(new T(t1, t2, t3)) {}
~val2user() { delete ((T*)m_p); }
};
template<typename T>
struct ptr2user : user
{
ptr2user(T* t) : user((void*)t) {}
};
template<typename T>
struct ref2user : user
{
ref2user(T& t) : user(&t) {}
};
// to lua
template<typename T>
struct val2lua { static void invoke(lua_State *L, T& input){ new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(input); } };
template<typename T>
struct ptr2lua { static void invoke(lua_State *L, T* input){ if(input) new(lua_newuserdata(L, sizeof(ptr2user<T>))) ptr2user<T>(input); else lua_pushnil(L); } };
template<typename T>
struct ref2lua { static void invoke(lua_State *L, T& input){ new(lua_newuserdata(L, sizeof(ref2user<T>))) ref2user<T>(input); } };
template<typename T>
struct enum2lua { static void invoke(lua_State *L, T val) { lua_pushnumber(L, (int)val); } };
template<typename T>
struct object2lua
{
static void invoke(lua_State *L, T val)
{
if_<is_ptr<T>::value
,ptr2lua<base_type<T>::type>
,if_<is_ref<T>::value
,ref2lua<base_type<T>::type>
,val2lua<base_type<T>::type>
>::type
>::type::invoke(L, val);
class_<class_type<T>::type>::push_meta(L);
lua_setmetatable(L, -2);
}
};
template<typename T>
struct type2lua
{
static void invoke(lua_State *L, T val)
{
if_<is_enum<T>::value
,enum2lua<T>
,object2lua<T>
>::type::invoke(L, val);
};
};
//
template<typename T>
T func_(lua_State *L)
{
return user2type<T>::invoke(L, lua_upvalueindex(1));
}
// arguments
struct pop_
{
template<typename T>
static T invoke(lua_State *L, int index) { return lua2type<T>::invoke(L, index); }
template<>
static char* invoke(lua_State *L, int index) { return (char*)lua_tostring(L, index); }
template<>
static const char* invoke(lua_State *L, int index) { return (const char*)lua_tostring(L, index); }
template<>
static char invoke(lua_State *L, int index) { return (char)lua_tonumber(L, index); }
template<>
static unsigned char invoke(lua_State *L, int index) { return (unsigned char)lua_tonumber(L, index); }
template<>
static short invoke(lua_State *L, int index) { return (short)lua_tonumber(L, index); }
template<>
static unsigned short invoke(lua_State *L, int index) { return (unsigned short)lua_tonumber(L, index); }
template<>
static long invoke(lua_State *L, int index) { return (long)lua_tonumber(L, index); }
template<>
static unsigned long invoke(lua_State *L, int index) { return (unsigned long)lua_tonumber(L, index); }
template<>
static int invoke(lua_State *L, int index) { return (int)lua_tonumber(L, index); }
template<>
static unsigned int invoke(lua_State *L, int index) { return (unsigned int)lua_tonumber(L, index); }
template<>
static float invoke(lua_State *L, int index) { return (float)lua_tonumber(L, index); }
template<>
static double invoke(lua_State *L, int index) { return (double)lua_tonumber(L, index); }
template<>
static bool invoke(lua_State *L, int index) { return lua_toboolean(L, index) != 0; }
template<>
static void invoke(lua_State *L, int index) { return; }
template<>
static __int64 invoke(lua_State *L, int index)
{
if(lua_isnumber(L,index))
return (__int64)lua_tonumber(L, index);
else
return *(__int64*)lua_touserdata(L, index);
}
template<>
static unsigned __int64 invoke(lua_State *L, int index)
{
if(lua_isnumber(L,index))
return (unsigned __int64)lua_tonumber(L, index);
else
return *(unsigned __int64*)lua_touserdata(L, index);
}
};
// return value
struct push_
{
template<typename T>
static void invoke(lua_State *L, T ret) { type2lua<T>::invoke(L, ret); }
template<>
static void invoke(lua_State *L, char ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, unsigned char ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, short ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, unsigned short ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, long ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, unsigned long ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, int ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, unsigned int ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, float ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, double ret) { lua_pushnumber(L, ret); }
template<>
static void invoke(lua_State *L, char* ret) { lua_pushstring(L, ret); }
template<>
static void invoke(lua_State *L, const char* ret) { lua_pushstring(L, ret); }
template<>
static void invoke(lua_State *L, bool ret) { lua_pushboolean(L, ret); }
template<>
static void invoke(lua_State *L, lua_value* ret) { if(ret) ret->to_lua(L); else lua_pushnil(L); }
template<>
static void invoke(lua_State *L, __int64 ret)
{
*(__int64*)lua_newuserdata(L, sizeof(__int64)) = ret;
lua_pushstring(L, "__s64");
lua_gettable(L, LUA_GLOBALSINDEX);
lua_setmetatable(L, -2);
}
template<>
static void invoke(lua_State *L, unsigned __int64 ret)
{
*(unsigned __int64*)lua_newuserdata(L, sizeof(unsigned __int64)) = ret;
lua_pushstring(L, "__u64");
lua_gettable(L, LUA_GLOBALSINDEX);
lua_setmetatable(L, -2);
}
};
template<typename T>
struct ret_ { static const int value = 1; };
template<>
struct ret_<void> { static const int value = 0; };
// caller
template<typename T1=void, typename T2=void, typename T3=void, typename T4=void, typename T5=void>
struct caller
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,func_<RVal(*)(T1,T2,T3,T4,T5)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2),pop_::invoke<T3>(L,3),pop_::invoke<T4>(L,4),pop_::invoke<T5>(L,5))); }
template<>
static void invoke<void>(lua_State *L) { func_<void(*)(T1,T2,T3,T4,T5)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2),pop_::invoke<T3>(L,3),pop_::invoke<T4>(L,4),pop_::invoke<T5>(L,5)); }
};
template<typename T1, typename T2, typename T3, typename T4>
struct caller<T1,T2,T3,T4>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,func_<RVal(*)(T1,T2,T3,T4)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2),pop_::invoke<T3>(L,3),pop_::invoke<T4>(L,4))); }
template<>
static void invoke<void>(lua_State *L) { func_<void(*)(T1,T2,T3,T4)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2),pop_::invoke<T3>(L,3),pop_::invoke<T4>(L,4)); }
};
template<typename T1, typename T2, typename T3>
struct caller<T1,T2,T3>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,func_<RVal(*)(T1,T2,T3)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2),pop_::invoke<T3>(L,3))); }
template<>
static void invoke<void>(lua_State *L) { func_<void(*)(T1,T2,T3)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2),pop_::invoke<T3>(L,3)); }
};
template<typename T1, typename T2>
struct caller<T1,T2>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,func_<RVal(*)(T1,T2)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2))); }
template<>
static void invoke<void>(lua_State *L) { func_<void(*)(T1,T2)>(L)(pop_::invoke<T1>(L,1),pop_::invoke<T2>(L,2)); }
};
template<typename T1>
struct caller<T1>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,func_<RVal(*)(T1)>(L)(pop_::invoke<T1>(L,1))); }
template<>
static void invoke<void>(lua_State *L) { func_<void(*)(T1)>(L)(pop_::invoke<T1>(L,1)); }
};
template<>
struct caller<void>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,func_<RVal(*)()>(L)()); }
template<>
static void invoke<void>(lua_State *L) { func_<void(*)()>(L)(); }
};
// function
template<typename T1=void, typename T2=void, typename T3=void, typename T4=void, typename T5=void>
struct functor
{
template<typename RVal>
static int invoke(lua_State *L) { caller<T1,T2,T3,T4,T5>::invoke<RVal>(L); return ret_<RVal>::value; }
};
template<typename RVal>
void push_func(lua_State *L, RVal (*func)())
{
lua_pushcclosure(L, functor<>::invoke<RVal>, 1);
}
template<typename RVal,class T1>
void push_func(lua_State *L, RVal (*func)(T1))
{
lua_pushcclosure(L, functor<T1>::invoke<RVal>, 1);
}
template<typename RVal,class T1,class T2>
void push_func(lua_State *L, RVal (*func)(T1,T2))
{
lua_pushcclosure(L, functor<T1,T2>::invoke<RVal>, 1);
}
template<typename RVal,class T1,class T2, typename T3>
void push_func(lua_State *L, RVal (*func)(T1,T2,T3))
{
lua_pushcclosure(L, functor<T1,T2,T3>::invoke<RVal>, 1);
}
template<typename RVal,class T1,class T2, typename T3, typename T4>
void push_func(lua_State *L, RVal (*func)(T1,T2,T3,T4))
{
lua_pushcclosure(L, functor<T1,T2,T3,T4>::invoke<RVal>, 1);
}
template<typename RVal,class T1,class T2, typename T3, typename T4, typename T5>
void push_func(lua_State *L, RVal (*func)(T1,T2,T3,T4,T5))
{
lua_pushcclosure(L, functor<T1,T2,T3,T4,T5>::invoke<RVal>, 1);
}
// member variable
template<typename T>
T* this_(lua_State *L)
{
return pop_::invoke<T*>(L, 1);
}
struct var_base
{
virtual void get(lua_State *L) = 0;
virtual void set(lua_State *L) = 0;
};
template<typename T, typename V>
struct mem_var : var_base
{
V T::*_var;
mem_var(V T::*val) : _var(val) {}
void get(lua_State *L) { push_::invoke(L, this_<T>(L)->*(_var)); }
void set(lua_State *L) { this_<T>(L)->*(_var) = pop_::invoke<V>(L, 3); }
};
// member function
template<typename T,class T1=void, typename T2=void, typename T3=void, typename T4=void, typename T5=void>
struct mem_caller
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,(this_<T>(L)->*func_<RVal(T::*)(T1,T2,T3,T4,T5)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3),pop_::invoke<T3>(L,4),pop_::invoke<T4>(L,5),pop_::invoke<T5>(L,6))); }
template<>
static void invoke<void>(lua_State *L) { (this_<T>(L)->*func_<void(T::*)(T1,T2,T3,T4,T5)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3),pop_::invoke<T3>(L,4),pop_::invoke<T4>(L,5),pop_::invoke<T5>(L,6)); }
};
template<typename T, typename T1, typename T2, typename T3, typename T4>
struct mem_caller<T,T1,T2,T3,T4>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,(this_<T>(L)->*func_<RVal(T::*)(T1,T2,T3,T4)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3),pop_::invoke<T3>(L,4),pop_::invoke<T4>(L,5))); }
template<>
static void invoke<void>(lua_State *L) { (this_<T>(L)->*func_<void(T::*)(T1,T2,T3,T4)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3),pop_::invoke<T3>(L,4),pop_::invoke<T4>(L,5)); }
};
template<typename T, typename T1, typename T2, typename T3>
struct mem_caller<T,T1,T2,T3>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,(this_<T>(L)->*func_<RVal(T::*)(T1,T2,T3)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3),pop_::invoke<T3>(L,4))); }
template<>
static void invoke<void>(lua_State *L) { (this_<T>(L)->*func_<void(T::*)(T1,T2,T3)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3),pop_::invoke<T3>(L,4)); }
};
template<typename T, typename T1, typename T2>
struct mem_caller<T,T1, T2>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,(this_<T>(L)->*func_<RVal(T::*)(T1,T2)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3))); }
template<>
static void invoke<void>(lua_State *L) { (this_<T>(L)->*func_<void(T::*)(T1,T2)>(L))(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3)); }
};
template<typename T, typename T1>
struct mem_caller<T,T1>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,(this_<T>(L)->*func_<RVal(T::*)(T1)>(L))(pop_::invoke<T1>(L,2))); }
template<>
static void invoke<void>(lua_State *L) { (this_<T>(L)->*func_<void(T::*)(T1)>(L))(pop_::invoke<T1>(L,2)); }
};
template<typename T>
struct mem_caller<T>
{
template<typename RVal>
static void invoke(lua_State *L) { push_::invoke(L,(this_<T>(L)->*func_<RVal(T::*)()>(L))()); }
template<>
static void invoke<void>(lua_State *L) { (this_<T>(L)->*func_<void(T::*)()>(L))(); }
};
//
template<typename T, typename T1=void, typename T2=void, typename T3=void, typename T4=void, typename T5=void>
struct mem_functor
{
template<typename RVal>
static int invoke(lua_State *L) { mem_caller<T,T1,T2,T3,T4,T5>::invoke<RVal>(L); return ret_<RVal>::value; }
};
template<typename RVal, typename T>
void push_func(lua_State *L, RVal (T::*func)())
{
lua_pushcclosure(L, mem_functor<T>::invoke<RVal>, 1);
}
template<typename RVal, typename T>
void push_func(lua_State *L, RVal (T::*func)() const)
{
lua_pushcclosure(L, mem_functor<T>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1>
void push_func(lua_State *L, RVal (T::*func)(T1))
{
lua_pushcclosure(L, mem_functor<T,T1>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1>
void push_func(lua_State *L, RVal (T::*func)(T1) const)
{
lua_pushcclosure(L, mem_functor<T,T1>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2>
void push_func(lua_State *L, RVal (T::*func)(T1,T2))
{
lua_pushcclosure(L, mem_functor<T,T1,T2>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2>
void push_func(lua_State *L, RVal (T::*func)(T1,T2) const)
{
lua_pushcclosure(L, mem_functor<T,T1,T2>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2, typename T3>
void push_func(lua_State *L, RVal (T::*func)(T1,T2,T3))
{
lua_pushcclosure(L, mem_functor<T,T1,T2,T3>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2, typename T3>
void push_func(lua_State *L, RVal (T::*func)(T1,T2,T3) const)
{
lua_pushcclosure(L, mem_functor<T,T1,T2,T3>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4>
void push_func(lua_State *L, RVal (T::*func)(T1,T2,T3,T4))
{
lua_pushcclosure(L, mem_functor<T,T1,T2,T3,T4>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4>
void push_func(lua_State *L, RVal (T::*func)(T1,T2,T3,T4) const)
{
lua_pushcclosure(L, mem_functor<T,T1,T2,T3,T4>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
void push_func(lua_State *L, RVal (T::*func)(T1,T2,T3,T4,T5))
{
lua_pushcclosure(L, mem_functor<T,T1,T2,T3,T4,T5>::invoke<RVal>, 1);
}
template<typename RVal, typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
void push_func(lua_State *L, RVal (T::*func)(T1,T2,T3,T4,T5) const)
{
lua_pushcclosure(L, mem_functor<T,T1,T2,T3,T4,T5>::invoke<RVal>, 1);
}
// constructor
template<typename T1=void, typename T2=void, typename T3=void, typename T4=void>
struct constructor {};
template<typename T1, typename T2, typename T3>
struct constructor<T1,T2,T3>
{
template<typename T>
static void invoke(lua_State *L)
{
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3),pop_::invoke<T3>(L,4));
}
};
template<typename T1, typename T2>
struct constructor<T1,T2>
{
template<typename T>
static void invoke(lua_State *L)
{
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(pop_::invoke<T1>(L,2),pop_::invoke<T2>(L,3));
}
};
template<typename T1>
struct constructor<T1>
{
template<typename T>
static void invoke(lua_State *L)
{
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>(pop_::invoke<T1>(L,2));
}
};
template<>
struct constructor<void>
{
template<typename T>
static void invoke(lua_State *L)
{
new(lua_newuserdata(L, sizeof(val2user<T>))) val2user<T>();
}
};
template<typename T>
struct creator
{
template<typename CONSTRUCTOR>
static int invoke(lua_State *L)
{
CONSTRUCTOR::invoke<T>(L);
class_<class_type<T>::type>::push_meta(L);
lua_setmetatable(L, -2);
return 1;
}
};
// destroyer
template<typename T>
struct destroyer
{
static int invoke(lua_State *L)
{
((user*)lua_touserdata(L, 1))->~user();
return 0;
}
};
// get
int get_var(lua_State *L);
int set_var(lua_State *L);
// Tinker Function
template<typename F>
lua_obj def(const char* name, F func)
{
lua_State *L = lua_state::L();
lua_pushstring(L, name);
lua_pushlightuserdata(L, func);
push_func(L, func);
lua_settable(L, LUA_GLOBALSINDEX);
return lua_obj();
}
// Tinker Global
template<typename T>
lua_obj decl(const char* name, T object)
{
lua_State *L = lua_state::L();
lua_pushstring(L, name);
push_::invoke(L, object);
lua_settable(L, LUA_GLOBALSINDEX);
return lua_obj();
}
// Tinker Call
template<typename RVal>
RVal call(const char* name)
{
lua_State *L = lua_state::L();
lua_pushcclosure(L, _exception, 0);
lua_pushstring(L, name);
lua_gettable(L, LUA_GLOBALSINDEX);
if(lua_isfunction(L,-1))
{
lua_pcall(L, 0, ret_<RVal>::value, 1);
}
else
{
lua_pushfstring(L, "lua_tinker : attempt to call global `%s' (not a function)", name);
_exception(L);
}
lua_remove(L, 1);
return pop_::invoke<RVal>(L, -1);
}
template<typename RVal, typename T1>
RVal call(const char* name, T1 arg)
{
lua_State *L = lua_state::L();
lua_pushcclosure(L, _exception, 0);
lua_pushstring(L, name);
lua_gettable(L, LUA_GLOBALSINDEX);
push_::invoke(L, arg);
lua_pcall(L, 1, ret_<RVal>::value, 1);
lua_remove(L, 1);
return pop_::invoke<RVal>(L, -1);
}
template<typename RVal, typename T1, typename T2>
RVal call(const char* name, T1 arg1, T2 arg2)
{
lua_State *L = lua_state::L();
lua_pushcclosure(L, _exception, 0);
lua_pushstring(L, name);
lua_gettable(L, LUA_GLOBALSINDEX);
push_::invoke(L, arg1);
push_::invoke(L, arg2);
lua_pcall(L, 2, ret_<RVal>::value, 1);
lua_remove(L, 1);
return pop_::invoke<RVal>(L, -1);
}
template<typename RVal, typename T1, typename T2, typename T3>
RVal call(const char* name, T1 arg1, T2 arg2, T3 arg3)
{
lua_State *L = lua_state::L();
lua_pushcclosure(L, _exception, 0);
lua_pushstring(L, name);
lua_gettable(L, LUA_GLOBALSINDEX);
push_::invoke(L, arg1);
push_::invoke(L, arg2);
push_::invoke(L, arg3);
lua_pcall(L, 3, ret_<RVal>::value, 1);
lua_remove(L, 1);
return pop_::invoke<RVal>(L, -1);
}
// Tinker Class
template<typename T>
struct class_ : lua_obj
{
// initialize
class_(const char* name)
: m_L(lua_state::L())
{
_name(name);
lua_pushstring(m_L, name);
lua_newtable(m_L);
lua_pushstring(m_L, "__name");
lua_pushstring(m_L, name);
lua_rawset(m_L, -3);
lua_pushstring(m_L, "__index");
lua_pushcclosure(m_L, get_var, 0);
lua_rawset(m_L, -3);
lua_pushstring(m_L, "__newindex");
lua_pushcclosure(m_L, set_var, 0);
lua_rawset(m_L, -3);
lua_pushstring(m_L, "__gc");
lua_pushcclosure(m_L, destroyer<T>::invoke, 0);
lua_rawset(m_L, -3);
lua_settable(m_L, LUA_GLOBALSINDEX);
}
// constructor
template<typename CONSTRUCTOR>
class_<T>& def(CONSTRUCTOR)
{
class_<class_type<T>::type>::push_meta(m_L);
lua_newtable(m_L);
lua_pushstring(m_L, "__call");
lua_pushcclosure(m_L, creator<T>::invoke<CONSTRUCTOR>, 0);
lua_rawset(m_L, -3);
lua_setmetatable(m_L, -2);
lua_pop(m_L,1);
return *this;
}
// inheritence
template<typename P>
class_<T>& inh()
{
class_<class_type<T>::type>::push_meta(m_L);
lua_pushstring(m_L, "__parent");
class_<class_type<P>::type>::push_meta(m_L);
lua_rawset(m_L, -3);
lua_pop(m_L,1);
return *this;
}
// functions
template<typename F>
class_<T>& def(const char* name, F func)
{
class_<class_type<T>::type>::push_meta(m_L);
lua_pushstring(m_L, name);
new(lua_newuserdata(m_L,sizeof(F))) F(func);
push_func(m_L, func);
lua_rawset(m_L, -3);
lua_pop(m_L,1);
return *this;
}
// variables
template<typename BASE, typename VAR>
class_<T>& def_readwrite(const char* name, VAR BASE::*val)
{
class_<class_type<T>::type>::push_meta(m_L);
lua_pushstring(m_L, name);
new(lua_newuserdata(m_L,sizeof(mem_var<BASE,VAR>))) mem_var<BASE,VAR>(val);
lua_rawset(m_L, -3);
lua_pop(m_L,1);
return *this;
}
// metatable
static void push_meta(lua_State *L)
{
const char* name = _name();
if(name[0])
{
lua_pushstring(L, name);
lua_gettable(L, LUA_GLOBALSINDEX);
}
else
{
lua_pushnil(L);
}
}
// global name
static const char* _name(const char* name = NULL)
{
static char temp[256] = "";
if(name) strcpy(temp, name);
return temp;
}
lua_State* m_L;
};
} // namespace lua_tinker
#endif //_LUA_TINKER_H_
// Lua Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "lua_tinker/lua_tinker.h"
struct A
{
A(int v) : value(v) {}
int value;
};
struct base
{
base() {}
const char* is_base(){ return "this is base"; }
};
class test : public base
{
public:
test(int val) : _test(val) {}
~test() {}
const char* is_test(){ return "this is test"; }
void ret_void() {}
int ret_int() { return _test; }
int ret_mul(int m) const { return _test * m; }
A get() { return A(_test); }
void set(A a) { _test = a.value; }
int _test;
};
test g_test(11);
class parent : public lua_tinker::lua_value
{
public:
void to_lua(lua_State* L) { lua_tinker::push_::invoke(L, this); } // lua 肺 傈崔 窃荐
virtual const char* name() { return "parent"; }
int m_parent;
};
class child : public parent
{
public:
void to_lua(lua_State* L) { lua_tinker::push_::invoke(L, this); } // lua 肺 傈崔 窃荐
const char* name() { return "child"; }
int m_child;
};
class grandchild : public child
{
public:
void to_lua(lua_State* L) { lua_tinker::push_::invoke(L, this); } // lua 肺 傈崔 窃荐
const char* name() { return "grandchild"; }
int m_grandchild;
};
lua_tinker::lua_value* GetChild(int n)
{
static parent _parent;
static child _child;
static grandchild _grandchild;
if(n == 0)
return &_parent;
else if(n == 1)
return &_child;
else
return &_grandchild;
}
int _tmain(int argc, _TCHAR* argv[])
{
lua_State* L = lua_open();
// init Lua
luaopen_base(L);
luaopen_string(L);
luaopen_table(L);
lua_settop(L, 0);
// LuaTinker
lua_tinker::lua_state::open(L);
lua_tinker::class_<base>("base")
.def("is_base", &base::is_base)
;
lua_tinker::class_<test>("test")
.inh<base>()
.def(lua_tinker::constructor<int>())
.def("is_test", &test::is_test)
.def("ret_void", &test::ret_void)
.def("ret_int", &test::ret_int)
.def("ret_mul", &test::ret_mul)
.def("get", &test::get)
.def("set", &test::set)
.def_readwrite("_test", &test::_test)
;
lua_tinker::decl("g_test", &g_test);
lua_tinker::class_<parent>("parent")
.def("name", &parent::name)
.def_readwrite("m_parent", &parent::m_parent)
;
lua_tinker::class_<child>("child")
.inh<parent>()
.def_readwrite("m_child", &child::m_child)
;
lua_tinker::class_<grandchild>("grandchild")
.inh<child>()
.def_readwrite("m_grandchild", &grandchild::m_grandchild)
;
lua_tinker::def("GetChild", GetChild);
// lua_tinker 龋免 抛胶飘
lua_tinker::dofile(L, "test.lua");
lua_tinker::call<void>("print", "-------------------------- call<>");
lua_tinker::call<void>("dir", g_test);
lua_tinker::call<void>("print", "-------------------------- call<> finished");
char temp[1024];
while(true)
{
printf(">");
if(stricmp(gets(temp), "quit") == 0)
break;
lua_tinker::dostring(L, temp);
}
// close Lua
lua_close(L);
return 0;
}