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
Posted by: ny | (15) August 28, 2019 10:57 AM
Posted by: niqiu | (14) July 1, 2016 04:59 PM
Posted by: QSlash | (13) May 7, 2012 09:53 AM
Posted by: QSlash | (12) May 6, 2012 01:02 PM
Posted by: alioxp | (11) April 18, 2012 01:02 PM
Posted by: evilswords | (10) April 18, 2012 10:32 AM
Posted by: dwing | (9) April 18, 2012 09:38 AM
Posted by: crazy | (8) April 17, 2012 05:24 PM
Posted by: 义乌网站建设 | (7) April 17, 2012 05:12 PM
Posted by: rnd | (6) April 17, 2012 03:50 PM
Posted by: php | (5) April 15, 2012 05:07 PM
Posted by: dwing | (4) April 12, 2012 10:06 AM
Posted by: frank28_nfls | (3) April 12, 2012 09:18 AM
Posted by: lqk | (2) April 12, 2012 12:08 AM
Posted by: yanyucheng | (1) April 11, 2012 07:42 PM