C++调用LUA函数,可变参模板实现

来源:互联网 发布:js清空input内容 编辑:程序博客网 时间:2024/06/14 13:07

极其方便调用LUA函数,支持返回值方式:

调用示例:

luax_vcall("func_1", 12, 33, 4.0, "helloworld");

int result = luax_pvicall("utils.math.add", 20, 30, 100);


直接贴出代码:  


/* powerful lua call, vardic template. */#ifndef _POWERFUL_LUA_CALL_HELPER_#define _POWERFUL_LUA_CALL_HELPER_/// helperinline bool luax_assume_func(lua_State* L, const char* func);/// FUNCTION TEMPLATE: luax_vcalltemplate<typename..._Args> inlinevoid luax_vcall(const char*  func, const _Args&...args);template<typename _Result, typename..._Args> inline_Result luax_vxcall(const char*  func, const _Args&...args);/// TEMPLATE luax_vxcall aliastemplate<typename..._Args> inlineint luax_vicall(const char*  func, const _Args&...args);template<typename..._Args> inlinefloat luax_vfcall(const char*  func, const _Args&...args);template<typename..._Args> inlinedouble luax_vdcall(const char*  func, const _Args&...args);template<typename..._Args> inlinestd::string luax_vvcall(const char*  func, const _Args&...args);/// FUNCTION TEMPLATE: luax_vpcalltemplate<typename..._Args> inlinevoid luax_pvcall(const char*  func, const _Args&...args);template<typename _Result, typename..._Args> inline_Result luax_pvxcall(const char*  func, const _Args&...args);/// TEMPLATE luax_pvxcall aliastemplate<typename..._Args> inlineint luax_pvicall(const char*  func, const _Args&...args);template<typename..._Args> inlinefloat luax_pvfcall(const char*  func, const _Args&...args);template<typename..._Args> inlinedouble luax_pvdcall(const char*  func, const _Args&...args);template<typename..._Args> inlinestd::string luax_pvvcall(const char*  func, const _Args&...args);/// arg push helperinlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg){}inlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg, int arg){    ++carg;    if (lua_checkstack(L, 1))        lua_pushinteger(L, arg), ++narg;}inlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg, float arg){    ++carg;    if (lua_checkstack(L, 1))        lua_pushnumber(L, arg), ++narg;}inlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg, double arg){    ++carg;    if (lua_checkstack(L, 1))        lua_pushnumber(L, arg), ++narg;}inlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg, const char* arg){    ++carg;    if (lua_checkstack(L, 1))        lua_pushstring(L, arg), ++narg;}inlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg, const std::string& arg){    ++carg;    if (lua_checkstack(L, 1))        lua_pushlstring(L, arg.c_str(), arg.length()), ++narg;}inlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg, void* arg){    ++carg;    if (lua_checkstack(L, 1))        tolua_pushuserdata(L, arg), ++narg;}/// cocos2d-x object support#define LUAX_VCALL_ADD_CCOBJ_SUPPORT(type) \inline \void luax_vpusharg(lua_State* L, int& carg, int& narg, cocos2d::type* arg) \{ \    ++carg; \    if (lua_checkstack(L, 1)) \        object_to_luaval<cocos2d::type>(L, "cc." #type, arg),/*tolua_pushuserdata(L, arg),*/ ++narg; \}#define LUAX_VCALL_ADD_CCUI_SUPPORT(type) \inline \void luax_vpusharg(lua_State* L, int& carg, int& narg, type* arg) \{ \    ++carg; \    if (lua_checkstack(L, 1)) \        object_to_luaval<cocos2d::ui::type>(L, "ccui." #type, arg),/*tolua_pushuserdata(L, arg),*/ ++narg; \}LUAX_VCALL_ADD_CCOBJ_SUPPORT(Node)LUAX_VCALL_ADD_CCOBJ_SUPPORT(Scene)LUAX_VCALL_ADD_CCOBJ_SUPPORT(Layer)LUAX_VCALL_ADD_CCOBJ_SUPPORT(LayerColor)LUAX_VCALL_ADD_CCOBJ_SUPPORT(Sprite)template<typename _Ty, typename..._Args> inlinevoid luax_vpusharg(lua_State* L, int& carg, int& narg, _Ty arg1, const _Args&...args){    luax_vpusharg(L, carg, narg, arg1);    luax_vpusharg(L, carg, narg, args...);}template<typename _Ty> inline_Ty luax_getretval(lua_State* L);template<> inlineint luax_getretval<int>(lua_State* L){    if (lua_isnumber(L, -1)){        return lua_tointeger(L, -1);    }    return 0;}template<> inlinefloat luax_getretval<float>(lua_State* L){    if (lua_isnumber(L, -1)){        return lua_tonumber(L, -1);    }    return 0;}template<> inlinedouble luax_getretval<double>(lua_State* L){    if (lua_isnumber(L, -1)){        return lua_tonumber(L, -1);    }    return 0;}template<> inlinestd::string luax_getretval<std::string>(lua_State* L){    if (lua_isstring(L, -1)){        return lua_tostring(L, -1);    }    return 0;}template<typename..._Args> inlinevoid luax_vcall(const char*  func, const _Args&...args){    auto L = luax_get_L();    auto top = lua_gettop(L); // store stack    int carg = 0, narg = 0;    lua_getglobal(L, func);    if (!lua_isfunction(L, -1))    {    cocos2d::log("luax_vcall failed, function:%s not exist!", func);        goto err_exit;    }    luax_vpusharg(L, carg, narg, args...);    if (carg != narg) {    cocos2d::log("luax_vcall failed, argument exception:carg:%d,narg:%d", carg, narg);        goto err_exit;    }    if (lua_pcall(L, narg, 0, 0) != 0)    {    cocos2d::log("luax_vcall failed, func:%s", func);        goto err_exit;    }    lua_settop(L, top); // resume stackerr_exit:    lua_settop(L, top); // resume stack}inline bool luax_assume_func(lua_State* L, const char* func){    std::string source = func;    const char* orig = source.c_str();    const char* name = orig;    auto offst = 0;    auto end = 0;    end = source.find_first_of('.', offst);    if (end == std::string::npos)    { // assume _G.func        lua_getglobal(L, name);        if (lua_isfunction(L, -1))            return true;        else            return false;    }    // assume table    source[end] = '\0';    lua_getglobal(L, name);    if (!lua_istable(L, -1))        return false;    offst = end + 1;    // continue check sub table    while ((end = source.find_first_of('.', offst)) != std::string::npos)    { // assume table        source[end] = '\0';        name = orig + offst;        lua_getfield(L, -1, name);        if (!lua_istable(L, -1))        {            return false;        }        offst = end + 1;    }    // now assume function    name = orig + offst;    lua_getfield(L, -1, name);    return !!lua_isfunction(L, -1);}template<typename _Result, typename..._Args> inline_Result luax_vxcall(const char*  func, const _Args&...args){    auto L = luax_get_L();    auto top = lua_gettop(L); // store stack    _Result result;    int carg = 0, narg = 0;    lua_getglobal(L, func);    if (!lua_isfunction(L, -1))    {    cocos2d::log("luax_vcall failed, function:%s not exist!", func);        goto err_exit;    }    luax_vpusharg(L, carg, narg, args...);    if (carg != narg) {    cocos2d::log("luax_vcall failed, argument exception:carg:%d,narg:%d", carg, narg);        goto err_exit;    }    if (lua_pcall(L, narg, 1, 0) != 0)    {    cocos2d::log("luax_vcall failed, lua_pcall failed");        goto err_exit;    }    result = luax_getretval<_Result>(L);    lua_settop(L, top); // resume stack    return std::move(result);err_exit:    lua_settop(L, top); // resume stack    return _Result();}// TEMPLATE luax_vxcall aliastemplate<typename..._Args> inlineint luax_vicall(const char*  func, const _Args&...args){    return luax_vxcall<int>(func, args...);}template<typename..._Args> inlinefloat luax_vfcall(const char*  func, const _Args&...args){    return luax_vxcall<float>(func, args...);}template<typename..._Args> inlinedouble luax_vdcall(const char*  func, const _Args&...args){    return luax_vxcall<double>(func, args...);}template<typename..._Args> inlinestd::string luax_vvcall(const char*  func, const _Args&...args){    return luax_vxcall<std::string>(func, args...);}// support any talbe prefixtemplate<typename..._Args> inlinevoid luax_pvcall(const char* func, const _Args&...args){    auto L = luax_get_L();    auto top = lua_gettop(L); // store stack    int carg = 0, narg = 0;    if (!luax_assume_func(L, func))    {        cocos2d::log("luax_vcall failed, function:%s not exist!", func);        goto err_exit;    }do_call:    luax_vpusharg(L, carg, narg, args...);    if (carg != narg) {        goto err_exit;    }    if (lua_pcall(L, narg, 0, 0) != 0)    {        goto err_exit;    }    lua_settop(L, top); // resume stackerr_exit:    lua_settop(L, top); // resume stack}template<typename _Result, typename..._Args> inline_Result luax_pvxcall(const char*  func, const _Args&...args){    auto L = luax_get_L();    auto top = lua_gettop(L); // store stack    _Result result;    int carg = 0, narg = 0;    if (!luax_assume_func(L, func))    {        cocos2d::log("luax_vcall failed, function:%s not exist!", func);        goto err_exit;    }    luax_vpusharg(L, carg, narg, args...);    if (carg != narg) {        cocos2d::log("luax_vcall failed, argument exception:carg:%d,narg:%d", carg, narg);        goto err_exit;    }    if (lua_pcall(L, narg, 1, 0) != 0)    {        cocos2d::log("luax_vcall failed, lua_pcall failed");        goto err_exit;    }    result = luax_getretval<_Result>(L);    lua_settop(L, top); // resume stack    return std::move(result);err_exit:    lua_settop(L, top); // resume stack    return _Result();}template<typename..._Args> inlineint luax_pvicall(const char*  func, const _Args&...args){    return luax_pvxcall<int>(func, args...);}template<typename..._Args> inlinefloat luax_pvfcall(const char*  func, const _Args&...args){    return luax_pvxcall<float>(func, args...);}template<typename..._Args> inlinedouble luax_pvdcall(const char*  func, const _Args&...args){    return luax_pvxcall<double>(func, args...);}template<typename..._Args> inlinestd::string luax_pvvcall(const char*  func, const _Args&...args){    return luax_pvxcall<std::string>(func, args...);}#endif /* powerful lua call, vardic template. */


0 0
原创粉丝点击