20140218-lua binder另一只轮子的雏形(2014-01-02 20:08)

4 篇文章 0 订阅

书接上一回,继续补充xlb的功能。这次修改代码的代码比添加功能的代码还多,完成后大致包括

  • 添加了支持overload和override函数绑定,支持绑定属性;
  • 添加了构造函数绑定,释构函数绑定前面已经实现了,这次是把名字修改了;
  • 修改函数参数提取过程,支持非一对一提取,即是一个函数形参可以从lua_State中提取N个参数(0<=N<=lua_gettop(L)),不过这一功能的具体用途还不是很清晰;
  • 添加绑定函数执行过程错误提示;
  • xlb变成单个头文件的形式;

添加绑定常量得等下一回继续。从C++调用lua这部分还没开始,还有许多功能需要实现,向luabind等学习,继续丰富其功能。xlb没有使用upvalue,纯模板编译时确定,因为还有许多功能未实现,现在仍不知道这会不会带来麻烦。

测试代码:

for k,v in pairs(clsA) do
	print(k,v);
end
objC:override_();
local f = obj.override_;
f(objC);
local f = objC.override_;
f(objC);
print(objC);
print(objC.z);
print(objC.x);
objC.x = 1;
print(objC.x);
objC:b();
local f = objC.b;
print(another);
f(obj);
print(obj.x);
for k,v in pairs(getmetatable(obj)) do
	print(k,v);
end
print(tostring(obj));
obj:NoReturn(555);
obj:NoReturn();
obj:Add(1,2);
obj:Add2(1,2,3);
obj.Add2(obj,1,2,3);
print(g(54321));
foo();
foo(1);
x=clsA.new(777);
x:Complex(x);
x = nil;
collectgarbage();


执行结果:

new     function: 0040A128
clsC::override_
clsA::override_
clsC::override_
xLB_object: 0x0022FEC4
1234
333
1
base class clsB::b() method called
xLB_object: 0x0022FEDB
base class clsB::b() method called
111
__newindex      function: 0040AFC4
__tostring      function: 0040B150
xLB_meta        xLB_clsA
xLB_super       table: 005D9B20
xLB_ancient     table: 005D9AF8
__gc    function: 0040A860
__index function: 0040AE64
xLB_object: 0x0022FED0
obj:NoReturn[a=555]
obj:NoReturn[a=8888]
clsA::Add(1,2):3 called
clsA::Add(int,int,int):1+2+3=6 called
clsA::Add(int,int,int):1+2+3=6 called
g(54321)
54323
foo called.
foo called: 1
obj:Complex[clsA*=0x005d2890, pa->x=777]
(0x005d2890)x=777,free
(0x0022fec4)x=1,free
(0x0022fed0)x=111,free


luabind.h

#ifndef _XLBINDER_H
#define _XLBINDER_H

#include <ns/xlb.h>
#include <type_traits>

struct clsAnother {
};

xLB_xodeclare(clsAnother) {
}

struct clsB {
	void b() { printf("base class clsB::b() method called\n"); }
	int z = 1234;
};

struct clsA : public clsB {
	clsA(int a=0) : x(a) {}
	~clsA() { printf("(0x%p)x=%d,free\n", this,x); }
	int Add(int a, int& b);
	void Add(int a, int b, int c) const;
	int Del(int* a);
	int Modify(int& a);
	void NoReturn(int a);
	void Complex(clsA* pa);
	int x = 999;
	void override_() { printf("clsA::override_\n"); }
}; // end of clsA

struct clsC : public clsA {
	void override_() { printf("clsC::override_\n"); }
	int y = 1000;
};

xLB_xodeclare(clsB) {
	def("b", xLB_cfunction<decltype(&clsB::b), &clsB::b>);
	def_readwrite<decltype(&clsB::z), &clsB::z>("z");
}

struct My_vter : public xLB_vter {};
template<> struct My_vter::xLB_tir<clsA*> { using type = clsA*; };

struct My_lver : public xLB_lver {
	//template<class TUP_ELE, class V> struct xLB_tir {};
};
template<class TUP_ELE>
	struct My_lver::xLB_tir<TUP_ELE, clsA*> {
		template<class TUP>
		static inline void go(lua_State* L, TUP_ELE& tuple_val, TUP& tuple, xLB_ami& ami) {
			auto obj = xLB_getdynamicud<clsA>(L, ami.next_index);
			if (obj) {
				tuple_val= obj;
				++ami.next_index;
			} else {
				ami.type_match = XLB_AMI_BAD;
				ami.extmsg = "clsA* expected";
			}
		}
	};

//struct My_dfer : public xLB_dfer {
struct My_dfer {
	template<class TUP> static inline int go(TUP& tuple) {
		return xLB_defaultarguments(tuple, 8888);
	}
};

xLB_xodeclare(clsA) {
	super<clsB>();
	constructor("new", xLB_cfunction<decltype(&xLB_newer<int>),&xLB_newer<int>,xLB_dfer,xLB_idxer<>,xLB_pper,xLB_rner_newobj>);
	def("NoReturn", xLB_cfunction<decltype(&clsA::NoReturn), &clsA::NoReturn, My_dfer, xLB_idxer<0>>);
	def("Complex", xLB_cfunction<decltype(&clsA::Complex), &clsA::Complex>);
	def("Add2", xLB_cfunction<void (clsA::*)(int, int, int) const, &clsA::Add>);
	def("Add", xLB_cfunction<
				xLB_cfunction<int (clsA::*)(int,int&), &clsA::Add>
			, xLB_cfunction<void (clsA::*)(int,int,int) const, &clsA::Add>>);
	def_readwrite<decltype(&clsA::x), &clsA::x>("x");
	def("override_", xLB_cfunction<decltype(&clsA::override_), &clsA::override_>);
	destructor();
};

xLB_xodeclare(clsC) {
	super<clsA>();
	def("override_", xLB_cfunction<decltype(&clsC::override_), &clsC::override_>);
}

struct mytype {
	int a;
};

void foo(int a);
int g(int a);
int h(clsA* a);
void v(int n, ...);

#endif

xlbind.cpp

#include "xlbinder.h"

//----------------------------------------------------------------------
void foo(int a) { printf("foo called: %d\n", a); }
void foo() { printf("foo called. \n" ); }
int g(int a) { printf("g(%d)\n", a); return a+2; }
int h(clsA* a) { printf("h called: %d\n", a->x); return 0; }
int h2(clsA* a) { printf("h2 called: %d\n", a->x); return 0; }
void v(int n, ...) {
	printf("%d", n);
}

//----------------------------------------------------------------------
int clsA::Add(int a, int& b) { 
	printf("clsA::Add(%d,%d):%d called\n", a,b,a+b);
	return a+b; 
}
void clsA::Add(int a, int b, int c) const { 
	printf("clsA::Add(int,int,int):%d+%d+%d=%d called\n", a,b,c,a+b+c);
}
int clsA::Del(int* a) { printf("obj:Del[int* a=%d]\n", *a); return *a-=2; };
int clsA::Modify(int& a) { printf("obj:Modify[int& a=%d]\n", a); return a*=2; }
void clsA::NoReturn(int a) { printf("obj:NoReturn[a=%d]\n", a); }
void clsA::Complex(clsA* pa) { printf("obj:Complex[clsA*=0x%p, pa->x=%d]\n", (void*)pa, pa->x); }


//----------------------------------------------------------------------
xLB_xodefine(clsAnother);
xLB_xodefine(clsA);
xLB_xodefine(clsB);
xLB_xodefine(clsC);
//----------------------------------------------------------------------------

#define test(L, s) \
	printf("run[\n%s\n]\n", s); \
	luaL_loadstring(L, s); \
	if (lua_pcall(L, 0, LUA_MULTRET, 0)) { \
		printf("%s\n", lua_tostring(L, -1)); \
		lua_pop(L, 1); \
	} \

//----------------------------------------------------------------------------
int main(int argc, char** args) {
	auto L = luaL_newstate();
	luaL_openlibs(L);

	xLB_bindxo<clsAnother>(L);
	clsAnother another;
	xLB_xoglobal<clsAnother>(L, &another, "another");

	xLB_bindxo<clsB>(L);
	xLB_bindxo<clsA>(L);
	xLB_bindxo<clsC>(L);
	clsA obj;
	obj.x = 111;
	xLB_xoglobal<clsA>(L, &obj, "obj");
	clsC objC;
	objC.x = 333;
	objC.y = 100;
	xLB_xoglobal<clsC>(L, &objC, "objC");

	//lua_register(L, "v", (xLB_cfunction<decltype(&v), &v>));
	lua_register(L, "g", (xLB_cfunction<decltype(&g), &g>));
	lua_register(L, "foo", (xLB_cfunction<
				  xLB_cfunction<void (*)(int), &foo>
				, xLB_cfunction<void (*)(), &foo>
				>));

	if (argc>=2) {
		luaL_loadfile(L, args[1]); \
		if (lua_pcall(L, 0, LUA_MULTRET, 0)) { \
			printf("%s\n", lua_tostring(L, -1)); \
			lua_pop(L, 1); \
		}
	}
	lua_close(L);
	return 0;
}

xlb.h

#ifndef _XLB_H
#define _XLB_H

#include <iostream>
#include <vector>
#include <assert.h>
#include <cstring>
#include <tuple>
#include <memory>
#include <type_traits>
#include <array>
#include <unordered_map>
using namespace std;

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
} // lua header files

/*---------------------------------------------------------------------------
predeclare
-----------------------------------------------------------------------------*/
template<typename T> struct xLB_xotrait;
template<typename T> struct xLB_function;
template<typename T> struct xLB_xobase;
struct xLB_util;

#define luaL_reg luaL_Reg
#define XLB_TRAP_FLAG 0xFF
#define XLB_EXISTS_FLAG 0x1

// tir (Type Information Replenish)
/*---------------------------------------------------------------------------
xLB_ludwrap : light user data wrapp as user data
-----------------------------------------------------------------------------*/
/* @struct xLB_ludwrap
 * This template used to wrapper lightuserdata as userdata, and then we can
 * set metatable on its. It's instance life managered by C++ not by Lua. */
template<typename T> struct xLB_ludwrap {
	T* ptr(){ return __ptr; }
	T* operator->() { return __ptr; }
	xLB_ludwrap(T* ptr, bool del=false) : __ptr(ptr), __del(del) {}
	virtual ~xLB_ludwrap() { if (__del) { delete __ptr; } }
	protected:
	T* __ptr; /**< real object */
	bool __del; /**< delete __ptr when xLB_ludwrap was release */
}; // end of xLB_ludwrap


/*---------------------------------------------------------------------------
lua userdata and C++ object
-----------------------------------------------------------------------------*/
/** if the object specify by index is userdata then
 * 1. if it is instance of type xLB_ludwrap<T> then get T* address from it;
 * 2. if it is derived from T* then get T* from userdata;
 * otherwise return nullptr; */
template<typename T, const char meta[]>
T* xLB_getuserdata(lua_State* L, int index, xLB_ludwrap<T>** pWp = 0) {
	using w_t = xLB_ludwrap<T>;
	T* r = 0;
	if (lua_isuserdata(L, index)) {
		auto wp = reinterpret_cast<w_t*>(luaL_checkudata(L, index, meta));
		//auto wp = reinterpret_cast<w_t*>(lua_touserdata(L, index));
		if (wp) { r = wp->ptr(); if (pWp) { *pWp = wp; } }
	} //else { nb_warn(true, "userdata expected"); }
return r;
}

template<typename T>
inline T* xLB_getxo(lua_State* L, int index) {
	return xLB_getuserdata<T, xLB_xotrait<T>::meta_name>(L, index);
}
template<typename T, const char meta[]>
int xLB_gcobj(lua_State* L) {
	xLB_ludwrap<T>* wp = 0;
	xLB_getuserdata<T, meta>(L, 1, &wp);
	if (wp) { wp->~xLB_ludwrap<T>();}
	return 0;
}

template<typename T>
int xLB_gcxo(lua_State* L) {
	xLB_ludwrap<T>* wp = nullptr;
	xLB_getuserdata<T, xLB_xotrait<T>::meta_name>(L, 1, &wp);
	if (wp) { wp->~xLB_ludwrap<T>(); }
	return 0;
}

/*---------------------------------------------------------------------------
xLB_typelist
-----------------------------------------------------------------------------*/
template<class...types> struct xLB_typelist {
	static int const size = sizeof...(types);
};

/*---------------------------------------------------------------------------
xLB_creatidxer
-----------------------------------------------------------------------------*/
template<int...> struct xLB_idxer{}; 
template<int...RPI> using xLB_rpi = xLB_idxer<RPI...>; // xLB_idxer alias
using xLB_rier = xLB_idxer<>;

template<int, class Idxer, int> 
struct xLB_creatidxer;

template<int I, int...Idxs, int RM>
struct xLB_creatidxer<I, xLB_idxer<Idxs...>, RM> {
	using type = typename 
		xLB_creatidxer<I+1, xLB_idxer<Idxs..., I>, RM-1>::type;
};

template<int I, int...Idxs>
struct xLB_creatidxer<I, xLB_idxer<Idxs...>, 0> {
	typedef xLB_idxer<Idxs...> type;
};

template<typename ...Types> 
struct xLB_toidxer : 
	xLB_creatidxer<0, xLB_idxer<>, sizeof...(Types)> {};

/*---------------------------------------------------------------------------
xLB_arginfo
-----------------------------------------------------------------------------*/
struct xLB_arginfo {
	int from = 0;
	int to = 0;
	int type = 0;
};

/*---------------------------------------------------------------------------
xLB_typelist
-----------------------------------------------------------------------------*/
template<class VTER, class FT> struct xLB_typeforge {};

template<class VTER, class R, class Tx, class...A> 
	struct xLB_typeforge<VTER, R(Tx::*)(A...)> {
		using tuple_t = std::tuple<typename VTER::template xLB_tir<A>::type...>;
		using idxer_t = typename xLB_toidxer<A...>::type;
		using vter_arg_t = xLB_typelist<typename VTER::template xLB_tir<A>::type...>;
		using arg_t = xLB_typelist<A...>;
		using return_t = R;
		using obj_t = Tx;
		using arginfo_t = array<xLB_arginfo, sizeof...(A)>;
	};

template<class VTER, class R, class Tx, class...A> 
	struct xLB_typeforge<VTER, R(Tx::*)(A...) const> {
		using tuple_t = std::tuple<typename VTER::template xLB_tir<A>::type...>;
		using idxer_t = typename xLB_toidxer<A...>::type;
		using vter_arg_t = xLB_typelist<typename VTER::template xLB_tir<A>::type...>;
		using arg_t = xLB_typelist<A...>;
		using return_t = R;
		using obj_t = Tx;
		using arginfo_t = array<xLB_arginfo, sizeof...(A)>;
	};

template<class VTER, class R, class...A> 
	struct xLB_typeforge<VTER, R(*)(A...)> {
		using tuple_t = std::tuple<typename VTER::template xLB_tir<A>::type...>;
		using idxer_t = typename xLB_toidxer<A...>::type;
		using vter_arg_t = xLB_typelist<typename VTER::template xLB_tir<A>::type...>;
		using arg_t = xLB_typelist<A...>;
		using return_t = R;
		using obj_t = void;
		using arginfo_t = array<xLB_arginfo, sizeof...(A)>;
	};

/*---------------------------------------------------------------------------
xLB_return_void
-----------------------------------------------------------------------------*/
template<typename Tx> struct xLB_return_void {
	static const bool value = true;
};

template<typename Tx, class R, class ...A> 
struct xLB_return_void<R (Tx::*)(A...)> {
	static const bool value = std::is_void<R>::value;
};

template<class R, class ...A>
struct xLB_return_void<R (*)(A...)> {
	static const bool value = std::is_void<R>::value;
};

/*---------------------------------------------------------------------------
xLB_each
-----------------------------------------------------------------------------*/
struct xLB_each{ template<class ...T> xLB_each(T...) {} };

/*---------------------------------------------------------------------------
xLB_util
-----------------------------------------------------------------------------*/
struct xLB_util {
	static void xLB_userdata(lua_State* L, const char* LibName, lua_Number N) {
		luaL_newmetatable(L, LibName); // s: 1(ud), 2(metatable)
		lua_setmetatable(L, -2); // ud.metatable = metatable
	}

	static void newxometatable(lua_State* L, const char* meta, 
			const std::vector<luaL_reg>& rg_meta,
			const std::vector<const char*>& super_names) {
		luaL_newmetatable(L, meta);
		if (1 < rg_meta.size()) {
			luaL_setfuncs(L, &rg_meta.front(), 0);
		}
		// set metatable.metatable to itself
		lua_pushvalue(L, -1);
		lua_setmetatable(L, -2);

		lua_pushstring(L, "xLB_meta");
		lua_pushstring(L, meta);
		lua_rawset(L, -3);
		lua_pushstring(L, "xLB_ancient");
		lua_newtable(L);
		lua_rawset(L, -3);
		lua_pushstring(L, "xLB_super");
		lua_newtable(L);
		for (auto meta_name : super_names) {
			lua_pushstring(L, meta_name);
			lua_pushnumber(L, XLB_EXISTS_FLAG);
			lua_rawset(L, -3);
		}
		lua_rawset(L, -3);
		lua_pop(L, 1); // pop metatable
	}

	static void registertypetable(lua_State* L, const char* type_name, 
			std::vector<luaL_reg>& rg_type, int parent_table_index) {
		if (1 < rg_type.size()) {
			if (parent_table_index != 0) {
				lua_pushstring(L, type_name);
				luaL_newlib(L, &rg_type.front());
				if (parent_table_index < 0) { parent_table_index -= 2; }
				lua_rawset(L, parent_table_index);
			} else {
				luaL_newlib(L, &rg_type.front());
				lua_setglobal(L, type_name);
			}
		}
	}

	static int search_getter(lua_State* L, const char* meta_name,
			std::vector<const char*>& super_names) {
		int nfound = 0;
		for (auto meta_name : super_names) {
			lua_getfield(L, LUA_REGISTRYINDEX, meta_name);
			assert(lua_istable(L, -1));
			lua_pushstring(L, "__index");
			lua_rawget(L, -2);
			lua_pushvalue(L, 1);
			lua_pushvalue(L, 2);
			// Note: manual call __index, instead using lua_gettable
			// since the value one the 1 index must be userdata
			lua_pcall(L, 2, 1, 0); 
			lua_remove(L, -2); // remove metatable
			if (lua_isnil(L, -1)) {
				lua_pop(L, 1);
			} else {
				nfound = 1;
				break;
			}
		}
		return nfound;
	}

	static int search_setter(lua_State* L, const char* meta_name,
			std::vector<const char*>& super_names) {
		int nfound = 0;
		for (auto meta_name : super_names) {
			lua_getfield(L, LUA_REGISTRYINDEX, meta_name);
			assert(lua_istable(L, -1));
			lua_pushstring(L, "__newindex");
			lua_rawget(L, -2);
			lua_remove(L, -2); // remove metatable
			lua_pushvalue(L, 1);
			lua_pushvalue(L, 2);
			lua_pushvalue(L, 3);
			// Notes: push additional argument(XLB_TRAP_FLAG) for __newindex calling
			lua_pushnumber(L, XLB_TRAP_FLAG);
			// Note: manual call __newindex, instead using lua_settable
			// since the value one the 1 index must be userdata
			lua_pcall(L, 4, 1, 0); 
			if (lua_isnil(L, -1)) {
				lua_pop(L, 1);
			} else {
				nfound = 1;
				break;
			}
		}
		return nfound;
	}

	static bool isderiveduserdata(lua_State* L, int index, const char* meta_name) {
		//-1:xLB_super={...}
		std::vector<string> table_names;
		lua_pushnil(L);
		while (lua_next(L, index) != 0) {
			table_names.push_back(string(lua_tostring(L,-2)));
			lua_pop(L, 1);
		}
		while (!table_names.empty()) {
			string table_name = table_names.back();
			table_names.pop_back();
			if (table_name == meta_name) {
				return true;
			} else {
				lua_getfield(L, LUA_REGISTRYINDEX, table_name.c_str());
				lua_pushstring(L, "xLB_super");
				lua_rawget(L, -2);
				if (lua_istable(L, -1)) { 
					auto table_index = lua_gettop(L);
					lua_pushnil(L);
					while (lua_next(L, table_index) != 0) {
						table_names.push_back(string(lua_tostring(L, -2)));
						lua_pop(L, 1);
					}
				}
				lua_pop(L, 2);
			}
		}
		return false;
	}

	static bool dynamic(lua_State* L, int index, const char* meta_name) {
		bool isderived = false;
		if (lua_isuserdata(L, index)) {
			lua_getmetatable(L, index);
			lua_pushstring(L, "xLB_meta");
			lua_rawget(L, -2);
			isderived = (strcmp(meta_name, lua_tostring(L, -1)) == 0);
			lua_pop(L, 1); // pop xLB_meta's value
			if (!isderived) {
				lua_pushstring(L, "xLB_ancient");
				lua_rawget(L, -2);
				if (!lua_istable(L, -1)) {
					lua_pop(L, 1);
					lua_pushstring(L, "xLB_ancient");
					lua_newtable(L);
					lua_rawset(L, -3);
					lua_pushstring(L, "xLB_ancient");
					lua_rawget(L, -2);
				}
				lua_pushstring(L, meta_name);
				lua_rawget(L, -2);
				isderived = !lua_isnil(L, -1);
				lua_pop(L, 2);
				if (!isderived) {
					lua_pushstring(L, "xLB_super");
					lua_rawget(L, -2);
					if (lua_istable(L, -1)) {
						isderived = xLB_util::isderiveduserdata(L, lua_gettop(L), meta_name);
					}
					lua_pop(L, 1); // xLB_super's value
					if (isderived) {
						lua_pushstring(L, "xLB_ancient");
						lua_rawget(L, -2);
						lua_pushstring(L, meta_name);
						lua_pushnumber(L, 1);
						lua_rawset(L, -3);
						lua_pop(L, 1);
					}
				}
			}
			lua_pop(L, 1); // pop metatable
		}
		return isderived;
	}
};


/* Wrap xo as Lua ud, and Lua do not charge object's life. */
template<typename T>
void xLB_wrapxo(lua_State* L, T* obj) {
	typedef xLB_ludwrap<T> w_t;
	auto place = (w_t*)(lua_newuserdata(L, sizeof(w_t)));
	new(place) w_t(obj/*,false*/);
	xLB_util::xLB_userdata(L, xLB_xotrait<T>::meta_name, 0);
}

template<typename T, const char meta[]>
void xLB_objasud(lua_State* L, T* obj) {
	typedef xLB_ludwrap<T> w_t;
	auto place = (w_t*)(lua_newuserdata(L, sizeof(w_t)));
	new(place) w_t(obj, true);
	xLB_util::xLB_userdata(L, meta, 0);
}

/* Wrap xo as Lua ud, means Lua charge object's life. */
template<typename T>
void xLB_xoasud(lua_State* L, T* obj) {
	typedef xLB_ludwrap<T> w_t;
	w_t* place = static_cast<w_t*>(lua_newuserdata(L, sizeof(w_t)));
	new(place) w_t(obj, true);
	xLB_util::xLB_userdata(L, xLB_xotrait<T>::meta_name, 0);
}

template<typename T, typename...A>
T* xLB_newxo(lua_State* L, A...arg_metas) {
	T* pobj = new T(arg_metas...);
	xLB_objasud<T, xLB_xotrait<T>::meta_name>(L, pobj);
	return pobj;
}

/*---------------------------------------------------------------------------
xLB_getdynamicud
-----------------------------------------------------------------------------*/
template<class T>
inline T* xLB_getdynamicud(lua_State* L, int index) {
	if (xLB_util::dynamic(L, index, xLB_xotrait<T>::meta_name)) {
		auto wp = reinterpret_cast<xLB_ludwrap<T>*>(lua_touserdata(L, index)); // index>0
		return wp->ptr();
	} else {
		return nullptr;
	}
}

/*---------------------------------------------------------------------------
xLB_dfer
function default parameters provider
-----------------------------------------------------------------------------*/
struct xLB_dfer {
	//template<class TUP> struct xLB_tir {
		//static inline int go(TUP& tuple) { return 0; }
	//};
	template<class TUP>
		static inline int go(TUP& tuple) { return 0; }
};

template<class TUP, class T, int Idx>
static inline void xLB_default_assign(TUP& tuple, const T& A) {
	std::get<Idx>(tuple) = A;
}

template<int BaseIdx, class TUP, class Idxer, class...T>
struct xLB_setdp {};

template<int BaseIdx, class TUP, int...Idxs, class...T>
struct xLB_setdp<BaseIdx, TUP, xLB_idxer<Idxs...>, T...> {
	static inline void go(TUP& tuple, T...DA) {
		xLB_each { 
			(xLB_default_assign<TUP, T, BaseIdx+Idxs>(tuple,DA),1)...
		};
	}
};

template<class TUP, class...T>
static inline int xLB_defaultarguments(TUP& tuple, T...DA) {
	using idxer_t = typename xLB_toidxer<T...>::type;
	xLB_setdp<std::tuple_size<TUP>::value - sizeof...(T), TUP, idxer_t, T...>
		::go(tuple, DA...);
	return sizeof...(DA);
}

/*---------------------------------------------------------------------------
xLB type match
-----------------------------------------------------------------------------*/
#define XLB_AMI_BAD           0x10000000
#define XLB_AMI_DENY          0x10000001
#define XLB_AMI_NONE          0x10000002
#define XLB_AMI_FEW           0x10000003
#define XLB_AMI_TOMUCH        0x10000003
#define XLB_AMI_SAME          0x0
#define XLB_AMI_DEFAULT       0x0
#define XLB_AMI_TRANSLATE     0x1
#define xLB_badtype(tmi) (XLB_AMI_BAD <= (tmi.type_match))
struct xLB_ami {
	int type_match = XLB_AMI_SAME;
	int narg = 0;
	int next_index = 0;
	const char* extmsg = "";
	int top = 0;
	int default_count = 0;
	int arg_count = 0;
	int return_count = 0;
	void* obj = nullptr;
};

/*---------------------------------------------------------------------------
xLB_lver
-----------------------------------------------------------------------------*/
struct xLB_lver {
	template<class TUP_ELE, class V> struct xLB_tir {
		template<class TUP>
		static inline void go(lua_State* L, TUP_ELE& tuple_val, TUP& tuple, xLB_ami& ami) {
			ami.type_match = XLB_AMI_BAD;
			ami.extmsg = "xLB_lver not implemented";
		}
	};
};

template<class Tx>
struct xLB_lver::xLB_tir<Tx*, Tx> {
	template<class TUP>
	static inline void go(lua_State* L, Tx*& tuple_val, TUP& tuple, xLB_ami& ami) {
		auto obj = xLB_getdynamicud<Tx>(L, ami.next_index); // narg==1
		if (obj) {
			tuple_val = obj;
			++ami.next_index;
		} else {
			ami.type_match = XLB_AMI_BAD;
			ami.extmsg = "self invalid";
		}
	}
};

template<class TUP_ELE>
struct xLB_lver::xLB_tir<TUP_ELE, int> {
	template<class TUP>
	static inline void go(lua_State* L, TUP_ELE& tuple_val, TUP& tuple, xLB_ami& ami) {
		auto index = ami.next_index;
		if (lua_isnumber(L, index)) {
			tuple_val = lua_tointeger(L, index);
			++ami.next_index;
		} else {
			ami.type_match = XLB_AMI_BAD;
			ami.extmsg = "integer expected";
		}
	}
};

template<class TUP_ELE>
struct xLB_lver::xLB_tir<TUP_ELE, double> {
	template<class TUP>
	static inline void go(lua_State* L, TUP_ELE& tuple_val, TUP& tuple, xLB_ami& ami) {
		auto index = ami.next_index;
		if (lua_isnumber(L, index)) {
			tuple_val = lua_tonumber(L, index);
			++ami.next_index;
		} else {
			ami.type_match = XLB_AMI_BAD;
			ami.extmsg = "double expected";
		}
	}
};

/*---------------------------------------------------------------------------
xLB_fver
-----------------------------------------------------------------------------*/
template<class LVER, class TUP, class IDXER, class TYPELIST>
struct xLB_fver {};


template<class LVER, class TUP>
struct xLB_fver<LVER, TUP, xLB_idxer<>, xLB_typelist<>> {
	template<class ARGINFO>
	static inline void go(lua_State* L, TUP& tuple, ARGINFO& arginfo, xLB_ami& ami) { 
		if (ami.top >= ami.next_index) {
			ami.type_match = XLB_AMI_TOMUCH;
			ami.extmsg = "too much argument";
		}
	}
};

template<class LVER, class TUP, int narg, int...idxs, class Head, class...Tail>
struct xLB_fver<LVER, TUP, xLB_idxer<narg, idxs...>, xLB_typelist<Head, Tail...>> {
	template<class ARGINFO>
	static inline void go(lua_State* L, TUP& tuple, ARGINFO& arginfo, xLB_ami& ami) {
		if (ami.top >= ami.next_index) {
			ami.narg = narg; // Note:
			auto& ai = arginfo[narg];
			ai.from = ami.next_index;
			ai.type = lua_type(L, ami.next_index);
			LVER::template xLB_tir<typename std::tuple_element<narg, TUP>::type, Head>
					::go(L, std::get<narg>(tuple), tuple, ami);
			ai.to = ami.next_index-1;
		} else { ami.type_match = XLB_AMI_FEW; }

		if (xLB_badtype(ami)) {
			if (ami.type_match == XLB_AMI_FEW) {
				auto stack_remain = (ami.top - (ami.next_index - 1));
				auto arguments_remain = (ami.arg_count - ami.narg);
				if (stack_remain - arguments_remain + ami.default_count >= 0) {
					ami.type_match = XLB_AMI_DEFAULT;
				} else {
					ami.extmsg = "too few argument";
				}
			}
		} else {
			xLB_fver<LVER, TUP, xLB_idxer<idxs...>, xLB_typelist<Tail...>>
				::go(L, tuple, arginfo, ami);
		}
	}
};

/*---------------------------------------------------------------------------
xLB_pper
push data(parameters of function) into lua_State
-----------------------------------------------------------------------------*/
struct xLB_pper {
	template<typename T> struct xLB_tir {
		static inline void go(lua_State* L, int narg, T tuple_val, 
					const xLB_arginfo& ai, int& return_count) {
			static_assert(std::is_pod<T>::value, "xLB_pper is not implemented.\n");
			printf("xLB_pper is not implemented.\n");
			//lua_pushnumber(L, tuple_val); ++return_count; 
		}
	};
};

template<> struct xLB_pper::xLB_tir<int> { 
	static inline void go(lua_State* L, int narg, int tuple_val, 
				const xLB_arginfo& ai, int& return_count) { 
		lua_pushinteger(L, tuple_val); ++return_count; 
	}
};

template<> struct xLB_pper::xLB_tir<const char*> {
	static inline void go(lua_State* L, int narg, const char* tuple_val, 
				const xLB_arginfo& ai, int& return_count) { 
		lua_pushstring(L, tuple_val); ++return_count; 
	}
};

template<> struct xLB_pper::xLB_tir<double> { 
	static inline void go(lua_State* L, int narg, double tuple_val, 
				const xLB_arginfo& ai, int& return_count) { 
		lua_pushnumber(L, tuple_val); ++return_count; 
	}
};

template<> struct xLB_pper::xLB_tir<long> { 
	static inline void go(lua_State* L, int narg, long tuple_val, 
				const xLB_arginfo& ai, int& return_count) { 
		lua_pushnumber(L, tuple_val); ++return_count; 
	}
};

template<> struct xLB_pper::xLB_tir<bool> { 
	static inline void go(lua_State* L, int narg, bool tuple_val, 
				const xLB_arginfo& ai, int& return_count) { 
		lua_pushnumber(L, tuple_val); ++return_count; 
	}
};

/*---------------------------------------------------------------------------
xLB_pter
push addition parameters of function into lua_State
-----------------------------------------------------------------------------*/
struct xLB_pter { template<class,class,class> struct xLB_tir {}; };

template<int...RPI,class...A,class PPER> 
struct xLB_pter::xLB_tir<xLB_idxer<RPI...>,std::tuple<A...>,PPER> {
	template<class ARGINFO>
	static inline void go(lua_State* L, std::tuple<A...>& tuple, ARGINFO& arginfo, int& return_count) {
		xLB_each{ 
				(PPER::template xLB_tir<
						typename std::tuple_element<RPI, std::tuple<A...>>::type
					>::go(L, RPI+1, std::get<RPI>(tuple), 
							reinterpret_cast<const xLB_arginfo&>(arginfo[RPI]), return_count), 1
				)... 
		};
	}
};

/*---------------------------------------------------------------------------
xLB_rner
push result of function into lua_State
-----------------------------------------------------------------------------*/
struct xLB_rner {
	template<class R, class PPER> struct xLB_tir {
		static inline void go(lua_State* L, int narg, const R& result_of_function, 
					const xLB_arginfo& ai, int& return_count) {
			PPER::template xLB_tir<R>::go(L, narg, result_of_function, ai, return_count);
		}
	};
};

struct xLB_rner_newobj : public xLB_rner { // customize for return wrapper object;
	template<class T, class PPER> struct xLB_tir {
		static inline void go(lua_State* L, int narg, T pobj, const xLB_arginfo& pai, int& return_count) {
			using OBJ_TYPE = typename std::remove_pointer<T>::type;
			xLB_objasud<OBJ_TYPE, xLB_xotrait<OBJ_TYPE>::meta_name>(L, pobj);
			++return_count;
		}
	};
};

/*---------------------------------------------------------------------------
xLB_vper
change type of value according to parameter's type for calling function
-----------------------------------------------------------------------------*/
struct xLB_vper {
	template<class To, class From> struct xLB_tir {
		static inline const To& go(const From& tuple_val) { return tuple_val; } 
	};
};

template<class T>struct xLB_vper::xLB_tir<T*, T*> {
	static inline T* go(T* tuple_val) { return tuple_val; } 
};

template<>struct xLB_vper::xLB_tir<int&, int> {
	static inline int& go(int& tuple_val) { return tuple_val; } 
};

template<>struct xLB_vper::xLB_tir<int*, int> {
	static inline int* go(int& tuple_val) { return &tuple_val; } 
};

/*---------------------------------------------------------------------------
xLB_vter
decide type of value for saving data come from lua_State
-----------------------------------------------------------------------------*/
struct xLB_vter {
	template<class PARAM_TYPE> struct xLB_tir { 
		using type = PARAM_TYPE;
		static_assert(std::is_pod<PARAM_TYPE>::value, "Warning: xLB_vter no implement\n"); 
	};
};

template<class PARAM_TYPE> struct xLB_vter::xLB_tir<PARAM_TYPE&> {
	using type = typename xLB_vter::xLB_tir<PARAM_TYPE>::type;
};

template<> struct xLB_vter::xLB_tir<int*> { using type = int; };
template<> struct xLB_vter::xLB_tir<int&> { using type = int; };
template<> struct xLB_vter::xLB_tir<double*> { using type = double; };

/*---------------------------------------------------------------------------
xLB_caler
-----------------------------------------------------------------------------*/
struct xLB_caler {
	template<class R, class Tx, class FT, class IDXER, class VPER, class TYPELIST, class RNER, class PPER> 
		struct xLB_tir {};
};

template<class R, class Tx, class FT, class VPER, class...A, int...idxs, class RNER, class PPER> 
struct xLB_caler::xLB_tir<R, Tx, FT, xLB_idxer<idxs...>, VPER, xLB_typelist<A...>, RNER, PPER> {
	template<class...B> static inline void go(lua_State* L, xLB_ami& ami, FT f, std::tuple<B...>& tuple) {
		R r = (reinterpret_cast<Tx*&>(ami.obj)->*f)(VPER::template xLB_tir<A,B>::go(std::get<idxs>(tuple))...);
		const xLB_arginfo ai;
		RNER::template xLB_tir<R,PPER>::go(L, 0, r, ai, ami.return_count);
	}
};

template<class Tx, class FT, class VPER, class...A, int...idxs, class RNER, class PPER> 
struct xLB_caler::xLB_tir<void, Tx, FT, xLB_idxer<idxs...>, VPER, xLB_typelist<A...>, RNER, PPER> {
	template<class...B> static inline void go(lua_State* L, xLB_ami& ami, FT f, std::tuple<B...>& tuple) {
			(reinterpret_cast<Tx*&>(ami.obj)->*f)(VPER::template xLB_tir<A,B>::go(std::get<idxs>(tuple))...);
		}
};

template<class R, class FT, class VPER, class...A, int...idxs, class RNER, class PPER> 
struct xLB_caler::xLB_tir<R, void, FT, xLB_idxer<idxs...>, VPER, xLB_typelist<A...>, RNER, PPER> {
	template<class...B> static inline void go(lua_State* L, xLB_ami& ami, FT f, std::tuple<B...>& tuple) {
		R r = f(VPER::template xLB_tir<A,B>::go(std::get<idxs>(tuple))...);
		const xLB_arginfo ai;
		RNER::template xLB_tir<R,PPER>::go(L, 0, r, ai, ami.return_count);
	}
};

template<class FT, class VPER, class...A, int...idxs, class RNER, class PPER> 
struct xLB_caler::xLB_tir<void, void, FT, xLB_idxer<idxs...>, VPER, xLB_typelist<A...>, RNER, PPER> {
	template<class...B> static inline void go(lua_State* L, xLB_ami&, FT f, std::tuple<B...>& tuple) {
		f(VPER::template xLB_tir<A,B>::go(std::get<idxs>(tuple))...);
	}
};

/*---------------------------------------------------------------------------
xLB_each_ovlfunc
-----------------------------------------------------------------------------*/
using xLB_ovlfunc = void (*)(lua_State* L, xLB_ami& ami);

template <xLB_ovlfunc... Fs>
struct xLB_each_ovlfunc_impl;

template <xLB_ovlfunc F>
struct xLB_each_ovlfunc_impl<F> {
	static void go(lua_State* L, xLB_ami& ami) {
		ami.type_match = XLB_AMI_SAME;
		F(L, ami);
	}
};

template <xLB_ovlfunc F, xLB_ovlfunc...Fs>
struct xLB_each_ovlfunc_impl<F, Fs...> {
	static inline void go(lua_State* L, xLB_ami& ami) {
		ami.type_match = XLB_AMI_SAME;
		F(L, ami);
		if (xLB_badtype(ami)) {
			xLB_each_ovlfunc_impl<Fs...>::go(L, ami);
		}
	}
};

template <xLB_ovlfunc...Fs>
inline void xLB_each_ovlfunc(lua_State* L, xLB_ami& ami) {
	xLB_each_ovlfunc_impl<Fs...>::go(L, ami);
}

/*---------------------------------------------------------------------------
xLB_loadobj
-----------------------------------------------------------------------------*/
template<class Tx, class LVER>
struct xLB_loadobj {
	template<class TUP, class ARGINFO>
	static inline void go(lua_State* L, TUP& tuple, xLB_ami& ami, ARGINFO& arginfo) {
		if (nullptr == ami.obj) {
			LVER::template xLB_tir<Tx*, Tx>::go(L, reinterpret_cast<Tx*&>(ami.obj), tuple, ami);
		}
	}
};

template<class LVER>
struct xLB_loadobj<void, LVER> {
	template<class TUP, class ARGINFO>
	static inline void go(lua_State*, TUP& tuple, xLB_ami&, ARGINFO& arginfo) {}
};

/*---------------------------------------------------------------------------
xLB_cfunction
overload function
-----------------------------------------------------------------------------*/
template<class FT, FT f, class DFER=xLB_dfer, class RIER=xLB_rier, 
		class PPER=xLB_pper, class RNER=xLB_rner, class PTER=xLB_pter, 
		class VTER=xLB_vter, class LVER=xLB_lver, class VPER=xLB_vper
>
void xLB_cfunction(lua_State* L, xLB_ami& ami) {
	using forge_t = xLB_typeforge<VTER, FT>;
	using tuple_t = typename forge_t::tuple_t;
	using idxer_t = typename forge_t::idxer_t;
	using vter_arg_t = typename forge_t::vter_arg_t;
	using arg_t = typename forge_t::arg_t;
	using return_t = typename forge_t::return_t;
	using obj_t = typename forge_t::obj_t;
	using arginfo_t = typename forge_t::arginfo_t;
	arginfo_t arginfo;
	tuple_t tuple;
	ami.next_index = 1;
	ami.narg = 0;
	xLB_loadobj<obj_t, LVER>::go(L, tuple, ami, arginfo);
	if (!xLB_badtype(ami)) {
		ami.default_count = DFER::go(tuple);
		ami.arg_count = arg_t::size;
		xLB_fver<LVER, tuple_t, idxer_t, vter_arg_t>::go(L, tuple, arginfo, ami);
	}
	ami.return_count = ami.type_match;
	if (!xLB_badtype(ami)) {
		xLB_caler::template xLB_tir<return_t, obj_t, FT, idxer_t, VPER, arg_t, RNER, PPER>
				::go(L, ami, f, tuple);
		PTER::template xLB_tir<RIER, tuple_t, PPER>::go(L, tuple, arginfo, ami.return_count);
	}
}

/*---------------------------------------------------------------------------
xLB_cfunction
overload function
-----------------------------------------------------------------------------*/
template<xLB_ovlfunc F, xLB_ovlfunc...Fs>
int xLB_cfunction(lua_State* L) {
	xLB_ami ami; 
	ami.top = lua_gettop(L);
	ami.obj = nullptr;
	xLB_each_ovlfunc<F, Fs...>(L, ami);
	if (xLB_badtype(ami)) {
		return luaL_argerror(L, ami.next_index, ami.extmsg);
	}
	return ami.return_count;
}

/*---------------------------------------------------------------------------
xLB_cfunction
normal function
-----------------------------------------------------------------------------*/
template<class FT, FT f, 
		class DFER=xLB_dfer,
		class RIER=xLB_rier, 
		class PPER=xLB_pper,
		class RNER=xLB_rner,
		class PTER=xLB_pter,
		class VTER=xLB_vter, 
		class LVER=xLB_lver, 
		class VPER=xLB_vper
> int xLB_cfunction(lua_State* L) {
	using forge_t = xLB_typeforge<VTER, FT>;
	using tuple_t = typename forge_t::tuple_t;
	using idxer_t = typename forge_t::idxer_t;
	using vter_arg_t = typename forge_t::vter_arg_t;
	using arg_t = typename forge_t::arg_t;
	using return_t = typename forge_t::return_t;
	using obj_t = typename forge_t::obj_t;
	using arginfo_t = typename forge_t::arginfo_t;
	arginfo_t arginfo;
	tuple_t tuple;
	xLB_ami ami; 
	ami.top = lua_gettop(L);
	ami.next_index = 1;
	xLB_loadobj<obj_t, LVER>::go(L, tuple, ami, arginfo);
	if (!xLB_badtype(ami)) {
		ami.default_count = DFER::go(tuple);
		ami.arg_count = arg_t::size;
		xLB_fver<LVER, tuple_t, idxer_t, vter_arg_t>::go(L, tuple, arginfo, ami);
	}
	if (xLB_badtype(ami)) {
		return luaL_argerror(L, ami.next_index, ami.extmsg);
	}
	ami.return_count = 0;
	xLB_caler::template xLB_tir<return_t, obj_t, FT,idxer_t,VPER, arg_t, RNER, PPER>
		::go(L, ami, f, tuple);
	PTER::template xLB_tir<RIER,tuple_t,PPER>::go(L, tuple, arginfo, ami.return_count);
	return ami.return_count;
}

/*---------------------------------------------------------------------------
xLB_getter
-----------------------------------------------------------------------------*/
template<class PT> struct xLB_proptype { };
template<class P, class Tx> struct xLB_proptype<P Tx::*> {
	using obj_t = Tx;
	using property_t = P;
};

template<class PT, PT property, class PPER>
int xLB_getter(lua_State* L) { // t,k
	using forge_t = xLB_proptype<PT>;
	using obj_t = typename forge_t::obj_t;
	using property_t = typename forge_t::property_t;
	// use wrapper to get obj pointer
	using wrap_t = xLB_ludwrap<obj_t>;
	auto wrap = reinterpret_cast<wrap_t*>(lua_touserdata(L, 1));
	auto obj = wrap->ptr(); assert(obj != nullptr);
	auto return_count = 0;
	if (obj) {
		xLB_arginfo ai;
		PPER::template xLB_tir<typename std::remove_reference<property_t>::type>
				::go(L, 1, (*obj).*property, ai, return_count);
	} else {
		printf("xLB_getdynamicud failed.\n");
	}
	return return_count;
}

template<class PT, PT property, class VTER, class LVER>
int xLB_setter(lua_State* L) { // t,k,v
	using forge_t = xLB_proptype<PT>;
	using obj_t = typename forge_t::obj_t;
	using property_t = typename forge_t::property_t;
	// use wrapper to get obj pointer
	using wrap_t = xLB_ludwrap<obj_t>;
	auto wrap = reinterpret_cast<wrap_t*>(lua_touserdata(L, 1));
	auto obj = wrap->ptr(); assert(obj != nullptr);
	auto return_count = 0;
	if (obj) {
		xLB_ami ami; 
		ami.top = lua_gettop(L);
		ami.obj = obj;
		ami.next_index = 3;
		using vter_t = typename VTER::template xLB_tir<property_t>::type;
		std::tuple<vter_t> tuple;
		LVER::template xLB_tir<vter_t,
				 property_t>::go(L, std::get<0>(tuple), tuple, ami);
		(*obj).*property = std::get<0>(tuple);
	} else {
		printf("xLB_getdynamicud failed.\n");
	}
	return return_count;
}

/*---------------------------------------------------------------------------
xLB binder
-----------------------------------------------------------------------------*/
template<typename T>
unique_ptr<xLB_xotrait<T>> xLB_newxobinder() {
	return unique_ptr<xLB_xotrait<T>>(new xLB_xotrait<T>());
}

template<typename T>
void xLB_bindxo(lua_State* L, int parent_table_index = 0) {
	xLB_xotrait<T>::register_(L, parent_table_index);
}

template<typename T>
void xLB_xoglobal(lua_State* L, T* obj, const char* name) {
	xLB_wrapxo(L, obj);
	lua_setglobal(L, name);
}

/*---------------------------------------------------------------------------
xLB_xomethod
-----------------------------------------------------------------------------*/
template<typename T> struct xLB_xomethod {
	using type = int (*)(lua_State*, T*);
};

template<typename R, typename T, typename... A>
struct xLB_xomethod<R (T::*)(A...) > {
	using type = R(T::*)(A...);
};

template<typename R, typename T, typename... A>
struct xLB_xomethod<R (T::*)(A...) const > {
	using type = R(T::*)(A...) const;
};

template<typename T, typename xLB_xomethod<T>::type f>
int xLB_xomethod_simple(lua_State* L) {
	int rc = 0;
	T* obj = xLB_getxo<T>(L, 1);
	if (obj) rc = f(L, obj);
	return rc;
}


/*---------------------------------------------------------------------------
luavar_info
-----------------------------------------------------------------------------*/
struct luavar_info {
	enum { readonly, readwrite, writeonly, function };
	int type;
	lua_CFunction getter;
	lua_CFunction setter;
};

/*---------------------------------------------------------------------------
xo macro
-----------------------------------------------------------------------------*/
#define xLB_xoinitmember(xo_t) \
template<> const char xLB_xobase<xo_t>::meta_name[]="xLB_"#xo_t; \
template<> const char xLB_xobase<xo_t>::type_name[]=#xo_t; \
template<> std::vector<const char*> xLB_xobase<xo_t>::super_names=std::vector<const char*>(); \
template<> std::vector<luaL_reg> xLB_xobase<xo_t>::rg_type={{nullptr,nullptr}}; \
template<> std::vector<luaL_reg> xLB_xobase<xo_t>::rg_meta={{nullptr,nullptr}}; \
template<> std::unordered_map<string, luavar_info> xLB_xobase<xo_t>::property_map={}; \

#define xLB_xodefineobj(xo_t) xLB_xotrait<xo_t> xLB_xo##xo_t; \

#define xLB_xodefine(xo_t) \
	xLB_xoinitmember(xo_t) \
	xLB_xodefineobj(xo_t) \

#define xLB_xodeclare(xo_t) \
	template<> struct xLB_xotrait<xo_t> : public xLB_xobase<xo_t> {\
		xLB_xotrait(); \
	}; \
	xLB_xotrait<xo_t>::xLB_xotrait() \


/*---------------------------------------------------------------------------
xLB_xotrait
-----------------------------------------------------------------------------*/
template<typename T> struct xLB_xotrait {};

/*---------------------------------------------------------------------------
xLB_xobase
-----------------------------------------------------------------------------*/
template<typename X>
struct xLB_xobase {
	typedef X T;
	typedef xLB_xobase self_t;
	typedef xLB_xobase* this_t;
	typedef xLB_xotrait<T> trait_t;
	typedef std::vector<luaL_reg> regs_t;
	static const char meta_name[];
	static const char type_name[];
	static std::vector<const char*> super_names;
	static regs_t rg_meta;
	static regs_t rg_type;
	static std::unordered_map<string, luavar_info> property_map;

	static inline void regfunc(const char fn[], lua_CFunction f) {
		property_map[fn] = { luavar_info::function, f, nullptr };
	}

	static int index_handler(lua_State* L) { //__index(t,k)
		auto var_name = luaL_optlstring(L, 2, "", nullptr);
		auto iter = property_map.find(var_name);
		int nfound = 0;
		if (iter != property_map.end()) {
			switch (iter->second.type) {
				case luavar_info::readonly:
				case luavar_info::readwrite:
					iter->second.getter(L);
					nfound = 1;
					break;
				case luavar_info::function:
					lua_pushcfunction(L, iter->second.getter);
					nfound = 1;
					break;
			}
		}
		if (0 == nfound) {
			nfound = xLB_util::search_getter(L, meta_name, super_names);
		}
		return nfound;
	}

	static int newindex_handler(lua_State* L) { // __newindex(t,k,v)
		auto var_name = luaL_optlstring(L, 2, "", nullptr);
		auto iter = property_map.find(var_name);
		auto top = lua_gettop(L);
		int nfound = 0;
		if (iter != property_map.end()) {
			switch (iter->second.type) {
				case luavar_info::writeonly:
				case luavar_info::readwrite:
					iter->second.setter(L);
					if (top == 4) { // meant called by search_setter
						lua_pushnumber(L, XLB_TRAP_FLAG);
					}
					nfound = 2;
				break;
			}
		}
		if (0 == nfound) {
			nfound = xLB_util::search_setter(L, meta_name, super_names);
		}
		if (2 == nfound) { // have found it
			if (4 == top) { nfound = 1; }
			else { nfound = 0; }
		} else {
			if (4 == top) { lua_pushnil(L); nfound = 1; }
		}
		return nfound;
	}

	static int tostring_handler(lua_State* L) {
		auto obj = xLB_getdynamicud<T>(L, 1);
		auto return_count = 1;
		if (obj) {
			lua_pushfstring(L, "xLB_object: 0x%p", obj);
		} else {
			lua_getglobal(L, "tostring");
			lua_pushvalue(L, 1);
			lua_pcall(L, 1, 1, 0);
		}
		return return_count;
	}

	template<class SUPER_XO> static void super() { 
		super_names.push_back(xLB_xotrait<SUPER_XO>::meta_name); 
	}

	template<lua_CFunction f> static void c(const char fn[]="new") { 
		rg_type.insert(begin(rg_type), {fn,f});
	}

	template<typename...A> static inline T* xLB_newer(A...arg_metas) { 
		return new T(arg_metas...); 
	}

	static void destructor() { 
		rg_meta.insert(begin(rg_meta), {"__gc", xLB_gcxo<T>});
	}

	template<typename xLB_xomethod<T>::type f> static void b(const char fn[]) { 
		regfunc(fn, xLB_xomethod_simple<T, f>);
	}

	template<lua_CFunction f> static void b(const char fn[]) { regfunc(fn, f); }

	static inline void def(const char fn[], lua_CFunction f) { regfunc(fn, f); }
	static inline void constructor(const char fn[], lua_CFunction f) {
		rg_type.insert(begin(rg_type), {fn, f});
	}
	template<class PT, PT property, class PPER=xLB_pper>
	static inline void def_readonly(const char property_name[]) {
		property_map[property_name] = { luavar_info::readonly, 
				xLB_getter<PT, property, PPER>,
				nullptr,
		};		
	}
	template<class PT, PT property, class PPER=xLB_pper, class VTER=xLB_vter, class LVER=xLB_lver>
	static inline void def_readwrite(const char property_name[]) {
		property_map[property_name] = { luavar_info::readwrite, 
				xLB_getter<PT, property, PPER>,
				xLB_setter<PT, property, VTER, LVER>,
		};		
	}

	static void register_(lua_State* L, int parent_table_index = 0) {
		rg_meta.insert(begin(rg_meta), {"__index", &index_handler});
		rg_meta.insert(begin(rg_meta), {"__newindex", &newindex_handler});
		rg_meta.insert(begin(rg_meta), {"__tostring", &tostring_handler});
		xLB_util::newxometatable(L, meta_name, rg_meta, super_names);
		xLB_util::registertypetable(L, trait_t::type_name, rg_type, parent_table_index);
	}
}; // end of xLB_xobase

#endif // end of __XLB_H__




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值