码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-06-30 13:06:58      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:c++   lua   

代码:

/// FUNCTION TEMPLATE: luax_vcall
template<typename..._Args> inline
void luax_vcall(const char*  func, _Args...args);

template<typename _Result, typename..._Args> inline
_Result luax_vxcall(const char*  func, _Args...args);

/// TEMPLATE luax_vxcall alias
template<typename..._Args> inline
int luax_vicall(const char*  func, _Args...args);

template<typename..._Args> inline
float luax_vfcall(const char*  func, _Args...args);

template<typename..._Args> inline
double luax_vdcall(const char*  func, _Args...args);

template<typename..._Args> inline
std::string luax_vvcall(const char*  func, _Args...args);

/// arg push helper
inline
void luax_vpusharg(lua_State* L, int& carg, int& narg)
{
}

template<typename _Ty> inline
void luax_vpusharg(lua_State* L, int& carg, int& narg, _Ty arg)
{
    static_assert(false, "error, luax_unpack:unsupported type!");
}

template<> inline
void luax_vpusharg<int>(lua_State* L, int& carg, int& narg, int arg)
{
    ++carg;
    if (lua_checkstack(L, 1))
        lua_pushinteger(L, arg), ++narg;
}

template<> inline
void luax_vpusharg<float>(lua_State* L, int& carg, int& narg, float arg)
{
    ++carg;
    if (lua_checkstack(L, 1))
        lua_pushnumber(L, arg), ++narg;
}

template<> inline
void luax_vpusharg<double>(lua_State* L, int& carg, int& narg, double arg)
{
    ++carg;
    if (lua_checkstack(L, 1))
        lua_pushnumber(L, arg), ++narg;
}

template<> inline
void luax_vpusharg<const char*>(lua_State* L, int& carg, int& narg, const char* arg)
{
    ++carg;
    if (lua_checkstack(L, 1))
        lua_pushstring(L, arg), ++narg;
}

template<> inline
void luax_vpusharg<const std::string&>(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;
}

template<typename _Ty, typename..._Args> inline
void luax_vpusharg(lua_State* L, int& carg, int& narg, _Ty arg1, _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<> inline
int luax_getretval<int>(lua_State* L)
{
    if (lua_isnumber(L, -1)){
        return lua_tointeger(L, -1);
    }
    return 0;
}

template<> inline
float luax_getretval<float>(lua_State* L)
{
    if (lua_isnumber(L, -1)){
        return lua_tonumber(L, -1);
    }
    return 0;
}

template<> inline
double luax_getretval<double>(lua_State* L)
{
    if (lua_isnumber(L, -1)){
        return lua_tonumber(L, -1);
    }
    return 0;
}

template<> inline
std::string luax_getretval<std::string>(lua_State* L)
{
    if (lua_isstring(L, -1)){
        return lua_tostring(L, -1);
    }
    return 0;
}

template<typename..._Args> inline
void luax_vcall(const char*  func, _Args...args)
{
    auto L = luax_get_L();

    auto top = lua_gettop(L); // store stack

    lua_getglobal(s_intriLuaS, func);
    if (!lua_isfunction(L, -1))
    {
        goto err_exit;
    }

    int carg = 0, narg = 0;
    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 stack

err_exit:
    lua_settop(L, top); // resume stack
}

template<typename _Result, typename..._Args> inline
_Result luax_vxcall(const char*  func, _Args...args)
{
    auto L = luax_get_L();

    auto top = lua_gettop(L); // store stack
    _Result result;

    lua_getglobal(s_intriLuaS, func);
    if (!lua_isfunction(L, -1))
    {
        goto err_exit;
    }

    int carg = 0, narg = 0;
    luax_vpusharg(L, carg, narg, args...);

    if (carg != narg) {
        goto err_exit;
    }

    if (lua_pcall(L, narg, 1, 0) != 0)
    {
        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 alias
template<typename..._Args> inline
int luax_vicall(const char*  func, _Args...args)
{
    return luax_vxcall<int>(func, args...);
}

template<typename..._Args> inline
float luax_vfcall(const char*  func, _Args...args)
{
    return luax_vxcall<float>(func, args...);
}

template<typename..._Args> inline
double luax_vdcall(const char*  func, _Args...args)
{
    return luax_vxcall<double>(func, args...);
}

template<typename..._Args> inline
std::string luax_vvcall(const char*  func, _Args...args)
{
    return luax_vxcall<std::string>(func, args...);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:c++   lua   

原文地址:http://blog.csdn.net/xseekerj/article/details/46692185

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!