lua中默認的number類型是double的,在游戲中很多數據類型用到了64位整型,雖然可以
通過重定義lua_Number為__int64以支持64位整型,但這又丟失了對浮點數的支持.
好在可以很方便的往lua中添加自定義的類型,我的需求很簡單,可以支持兩個i64,或1個
i64和一個lua_Number的基本算術和關系運算就夠了.
extern int newI64(lua_State *L); static const struct luaL_Reg i64Lib[] = { {"new",newI64}, {NULL,NULL}, }; class Integer64 { public: Integer64(__int64 val):m_val(val){} static void Register2Lua(lua_State *L) { luaL_getmetatable(L, "kenny.lualib"); lua_pushstring(L,"int64"); lua_newtable(L); lua_pushstring(L, "__add"); lua_pushcfunction(L, i64Add); lua_rawset(L, -3); lua_pushstring(L, "__sub"); lua_pushcfunction(L, i64Sub); lua_rawset(L, -3); lua_pushstring(L, "__div"); lua_pushcfunction(L, i64Div); lua_rawset(L, -3); lua_pushstring(L, "__mul"); lua_pushcfunction(L, i64Mul); lua_rawset(L, -3); lua_pushstring(L, "__mod"); lua_pushcfunction(L, i64Mod); lua_rawset(L, -3); lua_pushstring(L, "__eq"); lua_pushcfunction(L, i64Eq); lua_rawset(L, -3); lua_pushstring(L, "__lt"); lua_pushcfunction(L, i64Lt); lua_rawset(L, -3); lua_pushstring(L, "__le"); lua_pushcfunction(L, i64Le); lua_rawset(L, -3); lua_pushstring(L, "__tostring"); lua_pushcfunction(L, i64toString); lua_rawset(L, -3); lua_rawset(L,1); lua_pop(L,1); luaL_register(L,"i64",i64Lib); lua_pop(L,1); } static void setmetatable(lua_State *L) { luaL_getmetatable(L, "kenny.lualib"); lua_pushstring(L,"int64"); lua_gettable(L,-2); lua_setmetatable(L, -3); lua_pop(L,1); } #ifndef I64_RELA #define I64_RELA(OP)\ Integer64 *i64self = (Integer64 *)lua_touserdata(L,1);\ Integer64 *i64other = (Integer64 *)lua_touserdata(L,2);\ lua_pushboolean(L,i64self->m_val OP i64other->m_val);\ return 1; #endif static int i64Le(lua_State *L) { I64_RELA(<=); } static int i64Lt(lua_State *L) { I64_RELA(<); } static int i64Eq(lua_State *L) { I64_RELA(==); } #ifndef I64_MATH #define I64_MATH(OP)\ Integer64 *i64self = (Integer64 *)lua_touserdata(L,1);\ Integer64 *i64other = (Integer64 *)lua_touserdata(L,2);\ Integer64 tmp(0);\ if(!i64other)\ {\ tmp.m_val = lua_tonumber(L,2);\ i64other = &tmp;\ }\ if(!i64self)\ {\ long num = lua_tonumber(L,1);\ size_t nbytes = sizeof(Integer64);\ i64self = (Integer64*)lua_newuserdata(L, nbytes);\ new(i64self)Integer64(num);\ i64self->m_val OP= i64other->m_val;\ }else\ {\ i64self->m_val OP= i64other->m_val;\ lua_pushlightuserdata(L,i64self);\ }\ setmetatable(L);\ return 1; #endif static int i64Mod(lua_State *L) { I64_MATH(%); } static int i64Div(lua_State *L) { I64_MATH(/); } static int i64Mul(lua_State *L) { I64_MATH(*); } static int i64Add(lua_State *L) { I64_MATH(+); } static int i64Sub(lua_State *L) { I64_MATH(-); } static int i64toString(lua_State *L) { Integer64 *i64self = (Integer64 *)lua_touserdata(L,1); luaL_argcheck(L, i64self != NULL, 1, "userdata expected"); char temp[64]; sprintf(temp, "%I64d", i64self->m_val); lua_pushstring(L, temp); return 1; } private: __int64 m_val; }; static int newI64(lua_State *L) { Integer64 *tmp = (Integer64*)lua_touserdata(L,1); if(tmp) lua_pushlightuserdata(L,tmp); else { long initval = lua_tonumber(L,1); size_t nbytes = sizeof(Integer64); void *buf = lua_newuserdata(L, nbytes); new(buf)Integer64(initval); } Integer64::setmetatable(L); return 1; }
對於算術運算符而言,luaNumber op i64 或 i64 op luaNumber都沒問題,
比較遺憾的是關系運算符不能這樣,如果一個luaNumber於一個i64比較則要這樣寫:
local a = i64.new(100)
local b = 100
print(a == i64.new(b))