• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            colorful

            zc qq:1337220912

             

            Lua注冊(cè)回調(diào)到C++

            http://cn.cocos2d-x.org/tutorial/show?id=1896

            思路

            像所有語言一樣,綁定回調(diào)主要是執(zhí)行的任務(wù)執(zhí)行到特定情形的時(shí)候,調(diào)用對(duì)用回調(diào)方法。 本文也一樣,Lua注冊(cè)回調(diào)到C++的核心思路是,當(dāng)C代碼執(zhí)行到特定特定情形的時(shí)候,調(diào)用Lua的方法。

            我這里使用的是用lua_stack直接調(diào)用lua的方法,沒有使用Cocos2d-x封裝的那個(gè)dispatcher,因?yàn)槭煜つ莻€(gè)格式太墨跡了。


            主要步驟如下

            • 緩存Lua函數(shù)在Lua環(huán)境中的引用

            • 在C代碼的地方用C的方式設(shè)置好回調(diào)

            • 在C代碼回調(diào)函數(shù)執(zhí)行的時(shí)候,調(diào)用lua函數(shù)


            實(shí)現(xiàn)

            • C代碼綁定回調(diào),調(diào)用Lua函數(shù)

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            void ArmatureNode::registerMovementEventHandler(int handler)
            {
                unregisterMovementEventHandler();  //移除之前注冊(cè)的監(jiān)聽
                _movementHandler = handler;         //緩存lua函數(shù)的引用 這個(gè)后邊說
                 
                auto dispatcher = getCCEventDispatcher();
                 
                auto f = [this](cocos2d::EventCustom *event) //注冊(cè)c代碼形式的回調(diào) 這里用function做
                {
                    auto eventData = (dragonBones::EventData*)(event->getUserData());
                    auto type = (int) eventData->getType();
                    auto movementId = eventData->animationState->name;
                    auto lastState = eventData->armature->getAnimation()->getLastAnimationState();
                     
                    auto stack = cocos2d::LuaEngine::getInstance()->getLuaStack();
                    stack->pushObject(this"db.ArmatureNode");
                    stack->pushInt(type);
                    stack->pushString(movementId.c_str(), movementId.size());        
                    //通過LuaStack調(diào)用lua里的函數(shù)    最后一個(gè)參數(shù)設(shè)置參數(shù)個(gè)數(shù)
                    stack->executeFunctionByHandler(_movementHandler, 3);
                };
                 
                dispatcher->addCustomEventListener(dragonBones::EventData::COMPLETE, f);
            }
            void ArmatureNode::unregisterMovementEventHandler(void)
            {
                if (0 != _movementHandler)
                {
                    cocos2d::LuaEngine::getInstance()->removeScriptHandler(_movementHandler); //移除lua函數(shù)的綁定
                    _movementHandler = 0;
                }
            }
            • 提供Lua函數(shù)綁定到C的方法   

            上邊的這個(gè)函數(shù)直接用cocos里的genbinding.py 是無法正確生成Lua里可調(diào)用的接口的,需要手動(dòng)編寫綁定方法.

            說這個(gè)得用到Cocos2d-x中提供的一個(gè)方法:toluafix_ref_function會(huì)把一個(gè)Lua棧中的方法轉(zhuǎn)成一個(gè)int,以便C++中調(diào)用。我會(huì)在最后面說這個(gè)

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            int tolua_db_DBCCArmature_registerMovementEventHandler(lua_State* tolua_S)
            {
                if (NULL == tolua_S)
                    return 0;
                int argc = 0;
                 
                dragonBones::ArmatureNode* self = nullptr;
                self = static_cast<dragonBones::ArmatureNode*>(tolua_tousertype(tolua_S,1,0)); //第一個(gè)參數(shù) 就是lua里的self
                 
                argc = lua_gettop(tolua_S) - 1;
                 
                if (1 == argc)
                {
                    //第二個(gè)參數(shù),就是Lua里的function 這里要通過toluafix_ref_function這個(gè)函數(shù)映射成一個(gè)Int值
                    int handler = (toluafix_ref_function(tolua_S,2,0)); 
                    self->registerMovementEventHandler(handler);
                     
                    return 0;
                }
                return 0;
            }

             

            • 將綁定方法綁定到Lua環(huán)境里

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            int extends_ArmatureNode(lua_State* tolua_S)
            {
                lua_pushstring(tolua_S, "db.ArmatureNode");//之前db.ArmatureNode是通過腳本綁定在lua里。這里只做擴(kuò)展
                lua_rawget(tolua_S, LUA_REGISTRYINDEX);
                if (lua_istable(tolua_S,-1))
                {
                    lua_pushstring(tolua_S,"registerMovementEventHandler");
                    lua_pushcfunction(tolua_S,tolua_db_DBCCArmature_registerMovementEventHandler);
                    lua_rawset(tolua_S,-3);
                }
                 
                lua_pop(tolua_S, 1);
                return 0;
            }
            • Lua里設(shè)置回調(diào)到C++

            1
            2
            3
            4
            5
            6
            7
            8
             local arm = db.ArmatureNode:create("Dragon")
                local animation = arm:getAnimation()
                animation:gotoAndPlay("walk")
                arm:registerMovementEventHandler(
                    function(...)
                        print(...) 
                    end
                )


            -測(cè)試

            打印回調(diào)輸出,測(cè)試通過 userdata 8 walk


            其他

            • toluafix_ref_function 以及 toluafix_get_function_by_refid

            這 兩個(gè)方法是相互對(duì)應(yīng)的 toluafix_ref_function這個(gè)方法在注冊(cè)表上將一個(gè)lua的function與一個(gè)function_id生成映射 toluafix_get_function_by_refid 方法可以通過前一個(gè)方法生成的function_id來講綁定的lua function放到棧頂

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            //
            TOLUA_API int toluafix_ref_function(lua_State* L, int lo, int def)
            {
                if (!lua_isfunction(L, lo)) return 0;
                s_function_ref_id++;                            //function_id 加1
                lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);//在注冊(cè)表上,存放luafunction 映射table 的key壓棧
                lua_rawget(L, LUA_REGISTRYINDEX);               //獲取方法映射表,放在棧頂
                lua_pushinteger(L, s_function_ref_id);          //function_id壓棧
                lua_pushvalue(L, lo);                           //lo有效處索引處是lua方法,lua方法拷貝,壓棧
             
             
                lua_rawset(L, -3);                        //生成映射 
                lua_pop(L, 1);                                              
                return s_function_ref_id;
            }
            TOLUA_API void toluafix_get_function_by_refid(lua_State* L, int refid)
            {
                lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);            //存放luafunction 映射table 的key壓棧
                lua_rawget(L, LUA_REGISTRYINDEX);                           //獲取方法映射表,放在棧頂
                lua_pushinteger(L, refid);                                  //function_id壓棧
                lua_rawget(L, -2);                                          //獲取到的luafunction 放到棧頂
                lua_remove(L, -2);                                          //
            }
            • executeFunctionByHandler

            executeFunctionByHandler 這個(gè)方法只是通過toluafix_get_function_by_refid 獲取到function然后通過lua_pcall 方法調(diào)用,代碼就不寫了。

            posted on 2015-01-17 11:12 多彩人生 閱讀(2860) 評(píng)論(0)  編輯 收藏 引用 所屬分類: luaandroid cocos2dx

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            av无码久久久久久不卡网站| 中文字幕热久久久久久久| 日韩精品久久久久久久电影蜜臀| 精品多毛少妇人妻AV免费久久 | 伊人久久大香线焦AV综合影院| 国产激情久久久久影院| 久久成人18免费网站| 久久久久无码国产精品不卡| 国产精品美女久久久久av爽| 久久免费视频6| 国产精品久久精品| 一级做a爰片久久毛片毛片| 久久久国产精品亚洲一区| 久久精品国产99国产电影网| 亚洲精品无码久久毛片| 国产欧美久久久精品| 久久人人爽人人爽人人av东京热| 青青草国产精品久久久久| 欧美大香线蕉线伊人久久| 久久婷婷五月综合色99啪ak | 日本精品久久久久中文字幕| 大香伊人久久精品一区二区| 国产精品美女久久久免费| 国产99精品久久| 欧美黑人激情性久久| 国产成年无码久久久免费| 一级女性全黄久久生活片免费| 久久久久国产一级毛片高清板| 久久久久中文字幕| 国产精品女同久久久久电影院| 欧美精品乱码99久久蜜桃| 国产精品美女久久福利网站| 久久人搡人人玩人妻精品首页| 久久99国产精品久久| 国产成人久久精品区一区二区| 亚洲AV日韩精品久久久久| 久久人妻无码中文字幕| 天天综合久久一二三区| 亚洲精品国产综合久久一线| 亚洲国产精品嫩草影院久久| 午夜视频久久久久一区|