Cocos lua binding sentiment --- How tolua_isusertable and lua can access cocos static functions
I am still a newbie. I don't know much about it, so the language may be a bit obscure. Sorry !!
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;}
The Code simply means judging whether the data at the loc position in the stack is usertable. The general idea of the code is to retrieve the value A from the stack's loc location to find the value B in the Registry, and then compare the value B to determine whether it is of the type or const type. Therefore, it is obvious that A is the table corresponding to type or const type. When Will tolua_isusertable be called?
Simply search where tolua_isusertable is referenced. We can see that it is basically referenced in the create method, and there are some other methods. We can observe these functions carefully and find that they are all static functions, so I guess whether static functions will be generated when the lua and cocos intermediate layer code is generated? I also defined a static method in the Custom class with questions. I found that tolua_isusertable was generated.
Static methods can be called through classes. Therefore, before execution, you must determine whether the type passed by lua is the type of the class. This is the function of tolua_isusertable. Other member functions determine whether the passed userdata is of the type of this class.
For example:
local test = ccc.MyClass:create()
Here ccc. MyClass is a table, which is the data passed to the loc location of cocos. create is a static function in MyClass of C ++.
Conclusion: tolua_isusertable is used in functions called by lua directly through the table (C ++ class) to determine whether the table is of the C ++ type. Tolua_isuserdata is used in functions called through objects.
So the question is, can I use the lua variable to access static functions? I tried it and found that it was not good.
local test = ccc.MyClass:create() print(the first cocos bind lua result ..test:foo(2)) print(test:getData())
Program crash...
So there is no way to solve this problem? In fact, it is quite easy to change. Paste the intermediate code of getData first:
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 , 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;
The program crashes here. tolua finds that the passed table is not actually a userdata, so an error is reported !! We have changed it here. Just add a user to judge whether it is userdata !!
Change the line:
if (!tolua_isusertable(tolua_S,1,gls.MyClass,0,&tolua_err)&& !tolua_isusertype(tolua_S,1,gls.MyClass,0,&tolua_err)) goto tolua_lerror;