cocos2d-x3.3 lua调用webview回调函数

因为要用一个全屏网页覆盖整个游戏,需要能在js里直接调用lua的函数,网上搜了一圈没有发现怎样实现回调,自己写了份,共享给大家

1,把代码中的webview调通并且到处到lua,这步请自行搜索,网上一堆教程,这样就可以在lua中调用webview的大部分函数了
2,将几个需要回调的函数手动绑定,我因为只需要三个,就导出了setJsCallback,setOnDidCallback和setOnFailCallback
把下面的代码加入到lua_cocos2dx_ui_manual.cpp中

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

static int handleWebViewJSEvent(int handler, WebView* sender, const std::string& js)
{
    LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
    
    stack->pushObject(sender, "ccui.WebView");
    stack->pushString(js.c_str());
    
    stack->executeFunctionByHandler(handler, 2);
    stack->clean();
    
    return 0;
}

static int lua_cocos2dx_WebView_setJSCallback(lua_State* L)
{
    if (nullptr == L)
        return 0;
    
    int argc = 0;
    WebView* self = nullptr;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
    if (!tolua_isusertype(L,1,"ccui.WebView",0,&tolua_err)) goto tolua_lerror;
#endif
    
    self = static_cast(tolua_tousertype(L,1,0));
    
#if COCOS2D_DEBUG >= 1
    if (nullptr == self) {
        tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_WebView_setJSCallback'\n", NULL);
        return 0;
    }
#endif
    argc = lua_gettop(L) - 1;
    if (1 == argc)
    {
#if COCOS2D_DEBUG >= 1
        if (!toluafix_isfunction(L,2,"LUA_FUNCTION",0,&tolua_err))
        {
            goto tolua_lerror;
        }
#endif
        LUA_FUNCTION handler = (  toluafix_ref_function(L,2,0));

        self->setOnJSCallback(=](WebView *sender, const std::string &url){
            //CCLOG("OnJSCallback");
            handleWebViewJSEvent(handler, sender, url);
        });
        
        ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
        return 0;
    }
    
    luaL_error(L, "'setJSCallback' function of WebView has wrong number of arguments: %d, was expecting %d\n", argc, 1);
    return 0;
    
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(L,"#ferror in function 'setJSCallback'.",&tolua_err);
    return 0;
#endif
}

static int lua_cocos2dx_WebView_setOnDidCallback(lua_State* L)
{
    if (nullptr == L)
        return 0;
    
    int argc = 0;
    WebView* self = nullptr;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
    if (!tolua_isusertype(L,1,"ccui.WebView",0,&tolua_err)) goto tolua_lerror;
#endif
    
    self = static_cast(tolua_tousertype(L,1,0));
    
#if COCOS2D_DEBUG >= 1
    if (nullptr == self) {
        tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_WebView_setOnDidCallback'\n", NULL);
        return 0;
    }
#endif
    argc = lua_gettop(L) - 1;
    if (1 == argc)
    {
#if COCOS2D_DEBUG >= 1
        if (!toluafix_isfunction(L,2,"LUA_FUNCTION",0,&tolua_err))
        {
            goto tolua_lerror;
        }
#endif
        LUA_FUNCTION handler = (  toluafix_ref_function(L,2,0));

        self->setOnDidFinishLoading(=](WebView *sender, const std::string &url){
            //CCLOG("OnJSCallback");
            handleWebViewJSEvent(handler, sender, url);
        });
        
        ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
        return 0;
    }
    
    luaL_error(L, "'setOnDidCallback' function of WebView has wrong number of arguments: %d, was expecting %d\n", argc, 1);
    return 0;
    
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(L,"#ferror in function 'setOnDidCallback'.",&tolua_err);
    return 0;
#endif
}

static int lua_cocos2dx_WebView_setOnFailCallback(lua_State* L)
{
    if (nullptr == L)
        return 0;
    
    int argc = 0;
    WebView* self = nullptr;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
    if (!tolua_isusertype(L,1,"ccui.WebView",0,&tolua_err)) goto tolua_lerror;
#endif
    
    self = static_cast(tolua_tousertype(L,1,0));
    
#if COCOS2D_DEBUG >= 1
    if (nullptr == self) {
        tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_WebView_setOnFailCallback'\n", NULL);
        return 0;
    }
#endif
    argc = lua_gettop(L) - 1;
    if (1 == argc)
    {
#if COCOS2D_DEBUG >= 1
        if (!toluafix_isfunction(L,2,"LUA_FUNCTION",0,&tolua_err))
        {
            goto tolua_lerror;
        }
#endif
        LUA_FUNCTION handler = (  toluafix_ref_function(L,2,0));

        self->setOnDidFailLoading(=](WebView *sender, const std::string &url){
            //CCLOG("OnJSCallback");
            handleWebViewJSEvent(handler, sender, url);
        });
        
        ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
        return 0;
    }
    
    luaL_error(L, "'setOnFailCallback' function of WebView has wrong number of arguments: %d, was expecting %d\n", argc, 1);
    return 0;
    
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(L,"#ferror in function 'setOnFailCallback'.",&tolua_err);
    return 0;
#endif
}

static void extendWebView(lua_State* L)
{
    lua_pushstring(L, "ccui.WebView");
    lua_rawget(L, LUA_REGISTRYINDEX);
    if (lua_istable(L,-1))
    {
        tolua_function(L, "setJsCallback", lua_cocos2dx_WebView_setJSCallback);
        tolua_function(L, "setOnDidCallback", lua_cocos2dx_WebView_setOnDidCallback);
        tolua_function(L, "setOnFailCallback", lua_cocos2dx_WebView_setOnFailCallback);
    }
    lua_pop(L, 1);
}
#endif


```



3 将extendWebView函数加入到register_all_cocos2dx_ui_manual中进行注册
int register_all_cocos2dx_ui_manual(lua_State* L)
{
    if (nullptr == L)
        return 0;
    extendWidget(L);
    extendCheckBox(L);
    extendSlider(L);
    extendTextField(L);
    extendPageView(L);
    extendScrollView(L);
    extendListView(L);
    extendLayoutParameter(L);
    extendEditBox(L);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
 extendWebView(L);
#endif
    return 0;
}



4 在lua中调用webview代码


    local platform = cc.Application:getInstance():getTargetPlatform()
    if cc.PLATFORM_OS_ANDROID ~= platform then
        return
    end
    web = ccui.WebView:create()
    function jsCallback(sender, str)
        print("jsCallback ", str)
 if str == "lua://CloseHelp.lobby.command" then
            web:setVisible(false)
        end
    end
    local function didCallback(sender, str)
        print("didCallback ", str)
    end
    local function failCallback(sender, str)
        print("failCallback ", str)
    end

    web:setPosition(400,300)
    web:setContentSize(800,600)
    web:loadURL("http://www.baidu.com")
    web:setJavascriptInterfaceScheme("lua")
    web:setJsCallback(jsCallback) 
 web:setOnDidCallback(didCallback)
    web:setOnFailCallback(failCallback)
    mainScene:addChild(web)
    web:setVisible(false)
    --web:evaluateJS("alert(\"hello\")") 


```


5 注意事项
web:setJavascriptInterfaceScheme("lua")这个lua代表协议的类型,如http://baidu.com 这个值就是http,我们设置一个lua开头scheme,js里打开的所有链接,只要是lua开头的就会送回webview的callback
处理,而不会真的去打开链接。所以,要lua执行关闭的函数,直接在js网页中打开链接 "lua://CloseHelp.lobby.command"


web:evaluateJS("alert(\"hello\")") --使用此函数可以调用JavaScript中的函数


web:setJsCallback(jsCallback) 这个函数用local function不行,不知道为什么,所以直接用了个全局的函数,以后有空再查

请教cocos2dx c++ 调用webview回调函数的写法