|
问题
上文
分袂在C和C#层实现了Dump Lua Stack,
对Stack中的table类型,还进行了展开。
如果是table中的value是userdata、lightuserdata等类型,就会把lua_typename打印出来。
使用时发现,对lightuserdata类型,C层打印出来的是userdata,C#层打印出来的倒是lightuserdata,如下图(注意,我在这里分袂加了”-lua-“和”-C#-“):
C、C#版的逻辑是一样的,而C#版的方式理论上城市调到C层的native方式,理论上应该有不异的打印。
于是,研究一下为什么会分歧。
分析
C#层实现了本身的lua_typename
直接上源码:
/////---------Assets\ToLua\Examples\001_fp64\TestFP64Helper.cs
else
{
string typeName = L.LuaTypeName(L.LuaType(-1));
result += typeName ?? ”nil”;
result += ”\n”;
}
/////---------Assets\ToLua\Core\LuaStatePtr.cs
public LuaTypes LuaType(int index)
{
return LuaDLL.lua_type(L, index);
}
public string LuaTypeName(LuaTypes type)
{
return LuaDLL.lua_typename(L, type);
}
/////---------Assets\ToLua\Core\LuaDLL.cs
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern LuaTypes lua_type(IntPtr luaState, int index);
public static string[] LuaTypeName = { ”none”, ”nil”, ”boolean”, ”lightuserdata”, ”number”, ”string”, ”table”, ”function”, ”userdata”, ”thread” };
public static string lua_typename(IntPtr luaState, LuaTypes type)
{
int t = (int)type;
return LuaTypeName[t + 1];
}
按照代码我们知道,Tolua#的lua_type等方式,是会直接调用到native层的实现的,C#层只是一层包装。
而lua_typename纷歧样,lua_typename方式并没有直接调用native的lua_typename,
而是直接在C#层实现了一遍,直接用了C#层的方式,
LuaTypeName中定义了”lightuserdata”。
C层的实现
对应地,看一下在C层的,和C#的LuaTypeName“地位对等”的数组及相关代码。
代码如下:
/////---------tolua_runtime\luafixedpoint64\fp64helper.c
else
{
const char *typeName = lua_typename(L, lua_type(L, -1));
result = _malloc_concatenate_spaced_strings_free_first(result, typeName ? typeName : ”nil”);
result = _malloc_concatenate_strings_free_first(result, ”\n”);
}
/////---------tolua_runtime\macnojit\lua\lapi.c
/////---------tolua_runtime\luajit-2.1\src\host\minilua.c
LUA_API const char *lua_typename (lua_State *L, int t) {
UNUSED(L);
return (t == LUA_TNONE) ? ”no value” : luaT_typenames[t];
}
static const char*lua_typename(lua_State*L,int t){
UNUSED(L);
return(t==(-1))?”no value”:luaT_typenames[t];
}
/////---------tolua_runtime\macnojit\lua\ltm.c
/////---------tolua_runtime\luajit-2.1\src\host\minilua.c
static const char*const luaT_typenames[]={
”nil”,”boolean”,”userdata”,”number”,
”string”,”table”,”function”,”userdata”,”thread”,
”proto”,”upval”
};
/////---------tolua_runtime\macnojit\lua\lua.h
/////---------tolua_runtime\luajit-2.1\src\lua.h
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
/////---------tolua_runtime\macnojit\lua\lobject.h
/////---------tolua_runtime\luajit-2.1\src\lj_obj.h
/* tags for values visible from Lua */
#define LAST_TAG LUA_TTHREAD
#define NUM_TAGS (LAST_TAG+1)
/*
** Extra tags for non-values
*/
#define LUA_TPROTO (LAST_TAG+1)
#define LUA_TUPVAL (LAST_TAG+2)
#define LUA_TDEADKEY (LAST_TAG+3)我们知道,在C层,LIGHTUSERDATA的index为2,而数组luaT_typenames中index为2的是”userdata”。
在我看来,C层这里的”userdata”应该要改为”lightuserdata”,以便和后面的LUA_TUSERDATA 7对应的真正的”userdata”区分隔来。
我猜测,蒙占志(topameng,tolua作者) 也是这样认为,于是在C#层实现了本身的lua_typename方式,进行了上述改削,使得C#层的lua_typename方式能区分lightuserdata和userdata。
那回过头来想想,为什么lua的作者要定义lightuserdata和userdata的name都为“userdata”?
目前没有什么好的想法,猜测是有什么历史遗留问题导致的(具体是怎么样的历史遗留问题,就不清楚了)?
解决
其实可以不解决,让C/C#层按原生lua及Tolua#的实现来输出就好,知道此中的道理,有”纷歧致”这么一回事就好了。
这里也提供此外一种思路,
就是我们在C层也搞一个本身定义的lua_typename方式,区分lightuserdata和userdata,
在我们本身的东西类中使用。
代码如下:
/////---------tolua_runtime\luafixedpoint64\fp64helper.c
/////---------定义:
#ifndef UNUSED
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
#endif
static const char*const luaT_typenames_[]={
”nil”,”boolean”,”lightuserdata”,”number”,
”string”,”table”,”function”,”userdata”,”thread”,
”proto”,”upval”
};
const char *lua_typename_(lua_State *L, int t)
{
UNUSED(L);
return (t == LUA_TNONE) ? ”no value” : luaT_typenames_[t];
}
/////---------使用:
const char *typeName = lua_typename_(L, lua_type(L, -1));
result = _malloc_concatenate_spaced_strings_free_first(result, typeName ? typeName : ”nil”);
result = _malloc_concatenate_strings_free_first(result, ”\n”);小结
开发过程中遇到了一些疑惑,发现C及C#层的lua_typename方式表示纷歧致;
然后研究一下对应的C及C#源码,测验考试理解作者的思路;
最后给出了解决方案。
(转载请注明原始出处和原作者,添加原文链接张杰全:Tolua#下C及C#层的lua_typename方式的差异) |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|