|

楼主 |
发表于 2013-10-15 10:08:23
|
显示全部楼层
百度了一下,找到了些蛛丝马迹:
首先是一个lua capi和DX共用时一个要注意的地方. 在hge调用System_Initiate后(对D3D9设备初始化后), lua_tointeger,
luaL_checkinteger等从交换栈中取出整型数据的capi都永远返回0了(不管栈中数据是什么).
一开始感到很奇异,lua的capi怎么会和DX扯上关系. 对照lua的源码,发现失效的函数最终都是调用
了lua_tointeger, 而lua_tointeger是这样实现的
if (tonumber(o, &n)) {
lua_Integer res;
lua_Number num = nvalue(o);
lua_number2integer(res, num);
return res;
}
其意思是,首先尝试把n转换为lua_Number(包括n为String的情况),然后在通过lua_number2interger
这一宏来将lua_Number转换为lua_Integer, 即对浮点数取整.
然而, lua_number2interger为了优化效率实现了一些trick,如下(在luaconf.h中)
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) &&
(defined(__i386) || defined (_M_IX86) || defined(__i386__))
#if defined(_MSC_VER)
#define lua_number2int(i,d) __asm fld d __asm fistp i
#define lua_number2integer(i,n) lua_number2int(i, n)
#else
union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d)
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
#define lua_number2integer(i,n) lua_number2int(i, n)
#endif
#else
#define lua_number2int(i,d) ((i)=(int)(d))
#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
#endif
如果在Pentium处理器并且是用Ms的c编译器, 便通过内联asm来完成这操作:
fld d : 加载浮点数
fistp i: 浮点数取整出栈
如果不是Ms的c编译器,作者使用了一种trick
(据说是id Software的约翰·卡马克发明的, Wolfenstein 3D的作者 ^^)
union luai_Cast { double l_d; long l_l; };
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
但是注意作者的注释里提示到:可能会于Dx冲突, 因为在D3d中会调节FPU的运算精度,
而在低精度模式下,trick便失效.
... |
|