« 如何更准确的网络对时 | 返回首页 | 开发笔记(17) : 策划表格公式处理 »

Lua int64 的支持

虽然今天发了 twitter ,以及向 lua mailling list 里投递了消息,不过想想还是写一篇 blog 记录一下。

Lua 只支持一种 number ,默认是 double 类型。虽然你可以通过修改 luaconf.h 里的定义,把 lua number 改成 int64 。但是为了 int64 类型而放弃浮点数,恐怕不是大多数人想要的。

int64 通常用在 uuid 上,也就是说不需要对其数学运算,只需要可以比较就好了。我以前最喜欢的做法是用 8 bytes 长的 string 来表示一个 int64 。这样,即可以做唯一的 key 用,又不用做复杂的扩展。

pbc 的 lua binding 库 中,对 fixed64 类型,我就是这样处理的。

今天遇到新的需求,有同学希望可以在项目中直接处理 64bit 的 timestamp 。这就需要对 int64 做数学运算了。

虽然最终我们去掉了这个需求(使用 32bit 的 timestamp ),但我还是忍不住去想,到底怎样在 lua 中支持 64bit 整数运算最好。

在 luajit 中,是定义了一个 userdata 并重载其运算符完成的。即,你可以用 ffi.cast("int64_t",0) 来构造一个 64bit 的 0 。

姑且不谈 userdata 的额外开销问题,这样做有一个问题就是当 64bit 的 cdata 做 table 的 key 的时候,相同值的 int64 并不是同一个 key 。

我觉得有一个更轻量的方式来解决 int64 支持的问题。那就是在 64 位平台上,我们完全可以用 lightuserdata 无损失的表示一个 int64 。

通过给 lightuserdata 设置 metatable ,我们可以接管它的数据运算。唯一不足的是,比较一个 int64 和普通的 lua number 是否相等时,lua 不能隐式的做转换。(而大于小于比较则没有问题)

我花了半小时实现了我的想法,放在了 github 上 ,有兴趣的同学可以拿去用。

这个库只提供了一个显式的 api ,即构造一个 int64 数字。可以从 lua number 构造,也支持从一个 8 字节宽的小头的字符串来构造。实际在内存储存的是一个 lightuserdata 即一个 64bit 指针(所以这个库不适用于 32 位平台)。你也可以通过 C 接口 lua_pushlightuserdata 来把一个 64bit 整数压入堆栈。

把 int64 转换为普通的 lua number 借用了 # 操作符。

希望这个小东西对你有帮助。

Comments

您好,我在把luaconf.h的关于lua_number的定义全部修改成int类型之后,运行数字之后返回的结果是一个很大的数,个人感觉可能是内存地址,想问一下这种问题应该怎么解决?
你好,我在使用这个模块的时候出了点问题,希望能帮忙解答下。 我在我游戏进行初始化了很多表, local cBeanCfg=conf.host.new(luaBeanCfg); self.tableConfig[key].m_cache = conf.box(cBeanCfg),在各处逻辑都会去m_cache找到合适的数据;游戏 结束的时候我先清理了conf.host.delete(cBeanCfg)配置。但是我的主luaL_newstate_fullGC或者lua_close(L)的时候会崩掉。
lua_newuserdata这个快被废弃的API可以这时候用吧,如果lua_Alloc有合适的实现效率不会有太大问题
Only support 64bit architecture 还是不行吧 要不老实点,给lua_State*映射个小对象内存池 或者干脆扩展个lua_pushPOD
文化的重建,法制的独立,教育的普及是中国人精神层面前进面临的三个核心问题。 我们的历史过于悠久,各种思想都有流传,很多还相互矛盾。很多时候,评判事物都没有唯一的标准。儒家学说影响每个人的精神生活,但实际上,孔子在治理国家方面从来没有成功过。以德处事,以德治国,从来都是一种不切实际,因为,人之初,性本恶,以 法处事,以法治国,才是唯一正确的方式。我们的文艺复兴什么时候会来啊? 法制独立是一个理想,只有这个时候,才会有真正的公平和正义。但是,这个过程是艰难和曲折的,需要推动者极大的勇气,商鞅死了,王安石被贬了,戊戌6君子也死了,有的成功了有的失败了,为了国家和社会的未来,触犯了一些人的利益。中国啊,呼唤自 己的英雄。 如果每个人都了解了历史,了解了文化,了解了更多的内容,能承认自己的不足,能帮助他人,能以他人的利益为己任,成超越自己所处的位置,那么,这些理想就有可能实现。
luatinker也是用metatable这种方式的,分别实现了uint64和int64两种
@rnd 对于timestamp, Number正整数的52位有效数字也足够毫秒级别统计10+万年的了.
云里来,雾里去的
没看太明白,
有同学希望可以在项目中直接处理 64bit 的 timestamp 。这就需要对 int64 做数学运算了。 虽然最终我们去掉了这个需求(使用 32bit 的 timestamp 可能以后你会后悔的
不太懂。= =
number支持的53位整数我觉得在整数意义上已经足够用了, 而uuid这种应用通常还会需要128位的情况, 还有hash值等应用, 这些还是用string比较好.
没真正上过64位开发环境,这种只支持64位平台的,局限性有点大吧。另外,luaconf中不是定义了LUA_INTERGER嘛? /* @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ** machines, ptrdiff_t gives a good choice between int or long.) */ #define LUA_INTEGER ptrdiff_t
其他类型的lightuserdata也只能用这个metatable了?
你好牛。

Post a comment

非这个主题相关的留言请到:留言本