zoukankan      html  css  js  c++  java
  • cocos2dx v3.x lua绑定分析

    打算新项目转到cocos2dx v3上了,下载代码浏览过后发现改动真是非常大,结构性调整很多。

    比如tolua绑定这一块,就几乎全翻新了。

    胶水代码的生成,改成了全自动式的,通过clang来分析c++代码,可以准确的知道每一个类、函数、参数的信息,再也不用手动写pkg文件了。

    运行期对象管理这块,似乎也有了不少改动,至少我原来的一些扩展代码运行不了了,还没来得及细看,待看完再一一录下。

    先记录一下目前已看清楚的【类名表、类元表、对象实例】之间的关系:

    1、类元表:最核心的表,在lua代码里是不可见的。这是在注册每个类的第一步时建立的:

    tolua_usertype(tolua_S,"cc.Application");

    但其实类元表也就是一个普通的table,只不过它挂在lua registry上,所以说一般的逻辑代码是不会用到它的。类的所有函数、与父类的关系,也都记在这个核心的元表里。

    2、类名表:这就是lua代码里要使用该类时所用的名字,也就是:

    local app=cc.Application:getInstance()

    里cc.Application这个变量对应的表。它是注册类的第二步中建立的:

        tolua_cclass(tolua_S,"Application","cc.Application","",nullptr);

    【类名表】的元表就是【类元表】。

    3、对象实例:每个c++ object被push到lua里,是以一个userdata表示。它的元表被设成【类元表】,所对它调用的各种方法都会索引到相应的c++函数上。它的生成是在以下函数中完成:

    void tolua_pushusertype_internal (lua_State* L, void* value, const char* type, int addToRoot)

     

    其实在这里我不是太清楚每个类为什么要有两个表来表示,从功能上说,完全可以合为一个,也就是【类元表】上的所有功能都可以放在【类名表】里实现。也许是因为作者担心类名表存在于普通变量空间里,可能会被无意中修改覆写吧!但分开之后,也明显导致了一些后续处理上的麻烦:比如在给【模块】注册函数时,就要判断当前【模块】是一个【普通模块】(对应于c++里的名字空间)还是一个【类名表】,如果是后者,那函数不能直接挂在它上面,而是要转挂到【类元表】上去,这是在下面函数中处理的:

    /* Begin module
        * It pushes the module (or class) table on the stack
    */
    TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
    {
        if (name) { // ... module
    //---- now module[name] is a table, get it's metatable to store keys
            // get module[name]
            lua_pushstring(L,name); // ... module name
            lua_rawget(L,-2);       // ... module module[name]
            // Is module[name] a class table?
            lua_pushliteral(L, ".isclass");
            lua_rawget(L, -2);                  // stack: ... module module[name] class_flag
            if (lua_isnil(L, -1)) {
                lua_pop(L, 1);                  // stack: ... module module[name]
                return;                         // not a class table, use origin table
            }
            lua_pop(L, 1);                      // stack: ... module class_table
            // get metatable
            if (lua_getmetatable(L, -1)) {  // ... module class_table mt
                lua_remove(L, -2);          // ... module mt
            }
    //---- by SunLightJuly, 2014.6.5
        } else {
            lua_pushvalue(L,LUA_GLOBALSINDEX);
        }
    }
    

    同时这个修改也导致了我之前的一些代码运行失效。因为我会给一些类添加扩展函数,如:

    rawset(ccui.Widget,"set_enable", function(self, v)
      self:setTouchEnabled(v)
      self:setBright(v)
    end

    按上述逻辑,实例对象的元表直接指向类元表,也就是说完全绕过了类名表(类名表实际只在创建对象时起个提供类变量的引子作用),而rawset在类名表上的扩展函数自然也被忽略了。

    修改办法也很简单,去掉rawset,直接往类名表上写就行了,这会导致其通过元表上的class_newindex_event函数,把数据改记到类元表上,从而符合了实例对象的属性访问流程。

    至于之前为什么用一个rawset多此一举?那也是无奈之法,因为上一版本的cocos2dx在lua绑定实现上就是有点问题,不用rawset的话直接就挂了。所以说它现在又改好了,也算是回归自然吧。

     

  • 相关阅读:
    dedecms织梦建站总结
    ubuntu安装
    git命令
    关于测试日报
    Appium环境搭建(Windows版)
    jmeter,CSV数据加载、数据库连接、正则
    jmeter,参数、Bean Shell断言
    jmeter安装和组件说明
    造数据
    WEB UI自动化
  • 原文地址:https://www.cnblogs.com/wellbye/p/4295890.html
Copyright © 2011-2022 走看看