cocos lua绑定感悟---tolua_isusertable及lua如何访问cocos静态函数的方法

现在还是个新手,对很多还不是很了解,所以语言估计会有点晦涩,望原谅啊!!

TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
{
    if (def && lua_gettop(L)index = lo;
    err->array = 0;
    err->type = type;
    return 0;
}


 
   
  
static  int lua_isusertable (lua_State* L, int lo, const char* type)
{
    int r = 0;
    if (lo < 0) lo = lua_gettop(L)+lo+1;
    lua_pushvalue(L,lo);
    lua_rawget(L,LUA_REGISTRYINDEX);  /* get registry[t] */
    if (lua_isstring(L,-1))
    {
        r = strcmp(lua_tostring(L,-1),type)==0;
        if (!r)
        {
            /* try const */
            lua_pushstring(L,"const ");
            lua_insert(L,-2);
            lua_concat(L,2);
            r = lua_isstring(L,-1) && strcmp(lua_tostring(L,-1),type)==0;
        }
    }
    lua_pop(L, 1);
    return r;
}

代码的意思很简单,无非就是判断栈中 loc位置的数据是不是usertable。代码大概的思路就是从栈的loc位置取出值A,来在注册表中找到值B,然后对B进行字符串比较判断是不是type类型或者const type类型。所以很明显A就是type或者const type对应的table。那什么时候会调用tolua_isusertable呢?

索性就搜索一下tolua_isusertable 到底被哪里引用到了。看到基本上都是create方法中引用了,还有一些其他的方法,仔细观察这些函数,发现都是静态函数,所以就猜测 是不是静态函数在生成 lua 和cocos中间层代码的时候会被生成?我带着疑问就在自定义类中也定义了个静态方法,发现果然生成了tolua_isusertable。

静态方法可以通过类来调用,所以在执行之前要判断lua传递过来的是不是该类的类型。这就是tolua_isusertable的作用。而其它的成员函数是判断传递过来的是不是userdata,并且该userdata是不是该类的类型 。

举个例子吧:

local test = ccc.MyClass:create()

这里ccc.MyClass就是个table,是传递到cocos的loc位置的数据,create在C++的MyClass 中是静态函数。


总结:tolua_isusertable用在lua直接通过表(C++的类)来调用的函数中,判断这个表是不是对应的C++类型。而tolua_isuserdata用在通过对象调用的函数中。


那么问题来了,我可以通过lua变量来访问静态函数么?我试了下,发现不行也是坑爹货。


local test = ccc.MyClass:create()
	print("the first cocos bind lua result "..test:foo(2))
	print(test:getData())


 
  程序崩溃。。。 
  

那就没有办法来解决这个问题吗?其实要改的话,也挺简单。先贴下getData的中间代码吧:

int lua_myclass_MyClass_getData(lua_State* tolua_S)
{
    int argc = 0;
    bool ok  = true;

#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif

#if COCOS2D_DEBUG >= 1
  if (!tolua_isusertable(tolua_S,1,"gls.MyClass",0,&tolua_err))) goto tolua_lerror;
#endif

    argc = lua_gettop(tolua_S) - 1;

    if (argc == 0)
    {
        if(!ok)
            return 0;
        int ret = GameLogic::MyClass::getData();
        tolua_pushnumber(tolua_S,(lua_Number)ret);
        return 1;
    }
    CCLOG("%s has wrong number of arguments: %d, was expecting %d\n ", "getData",argc, 0);
    return 0;
#if COCOS2D_DEBUG >= 1
    tolua_lerror:
    tolua_error(tolua_S,"#ferror in function 'lua_myclass_MyClass_getData'.",&tolua_err);
#endif
    return 0;
}

 if (!tolua_isusertable(tolua_S,1,"gls.MyClass",0,&tolua_err))) goto tolua_lerror;

 
  程序就是在这里崩溃的,tolua发现传递过来的不是个table,其实它是个userdata,所以报错啦!!我们改的也是这里,加个判断是否是userdata就可以了嘛!! 
  

将那行改成:

if (!tolua_isusertable(tolua_S,1,"gls.MyClass",0,&tolua_err)
&& !tolua_isusertype(tolua_S,1,"gls.MyClass",0,&tolua_err)) goto tolua_lerror;


搞定啦!!


你可能感兴趣的:(cocos2d-x,lua)