tolua映射解析,以及如何在cocos2d-x里把自己的c++class映射到lua中

不管引擎多强大,总会自己拓展一些类. 或者使用一些有源码包. 用c++实现然后再映射到lua里.

1.映射

这个代码还是比较好懂,整个函数就是把类和所继承的类和对应的lua做一个映射. 然后做函数的映射;也就是把MyHttpClient的doGet函数映射到tolua_liangwei_MyHttpClient_doGet00函数里去, 由 tolua_liangwei_MyHttpClient_doGet00 去做 调用时参数的获取和转换, 然后再由tolua_liangwei_MyHttpClient_doGet00真正的调用MyHttpClient的doGet函数;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        TOLUA_API int tolua_liangwei_extension_open (lua_State* tolua_S)
        {
            tolua_open(tolua_S);

            //注册类型名
            tolua_usertype(tolua_S,"MyHttpClient");

            tolua_module(tolua_S,NULL,0);
            tolua_beginmodule(tolua_S,NULL);

            //注册函数和类
            tolua_cclass(tolua_S, "MyHttpClient", "MyHttpClient", "CCObject", NULL);
            tolua_beginmodule(tolua_S,"MyHttpClient");
            tolua_function(tolua_S,"doGet",tolua_liangwei_MyHttpClient_doGet00);
            tolua_endmodule(tolua_S);

            tolua_endmodule(tolua_S);
            return 1;
        }
    

2.然后来看tolua_liangwei_MyHttpClient_doGet00

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
        static int tolua_liangwei_MyHttpClient_doGet00(lua_State* tolua_S)
        {
            tolua_Error tolua_err;
            if (
                    //函数类型检测, 如果不满足就goto tolua_lerror报错
                    !tolua_isusertable(tolua_S,1,"MyHttpClient",0,&tolua_err) ||
                            !tolua_isstring(tolua_S,2,0,&tolua_err) ||
                            !tolua_isfunction(tolua_S,3,&tolua_err) ||
                            !tolua_isnoobj(tolua_S,4,&tolua_err)
                    )
                goto tolua_lerror;
            else
            {
                //满足, 取出第一个参数. tolua_tostring, 顾名思义 ,lua类型转换成c++的string(char *);
                const char* url = ((const char*)  tolua_tostring(tolua_S,2,0));
                //取出第二个参数, lua的function是一个int型的"描述符"
                int funcID = (tolua_ref_function(tolua_S,3,0));
                {
                    //真正调用方法;
                    MyHttpClient::doGet(url, funcID);
                }
            }
            return 1;
            tolua_lerror:
                    tolua_error(tolua_S,"#ferror in function 'node'.",&tolua_err);
            return 0;

        }
    

3.那么tolua_liangwei_extension_open 是什么时候”被”调用?一般在register lua engine 完成之后调用; 也就是在AppDelegate::applicationDidFinishLaunching() 中:

1
2
3
4
5
6
7
8
        // register lua engine
        CCScriptEngineProtocol* pEngine = CCLuaEngine::engine();
        CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);

        //注册自己的扩展
        lua_State* L = pEngine->getLuaState();
        tolua_liangwei_extension_open(L);
    

4.MyHttpClient 的原型:

1
2
3
4
5
6
7
8
9
10
11
        class MyHttpClient : public cocos2d::CCObject
        {
        public:
            static void doGet(const char* url,int handler);
            virtual void onHttpRequestCompleted(cocos2d::CCNode *sender, void *data);
            virtual void executeFunction(int responseCode, const char* resp);

        private:
            int m_nHandler;
        };
    

onHttpRequestCompleted和executeFunction 都不需要暴露给lua, 所以就不需要映射;