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))