向lua中添加i64的支持

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

原文地址:https://www.cnblogs.com/sniperHW/p/2471093.html