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...);
}

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

时间: 2024-10-31 22:22:18

C++调用LUA函数,可变参模板实现的相关文章

C中调用Lua函数

我们先来看一个简单的例子: lua_State* L = NULL; // 内部调用lua函数 double f(double x, double y) { double z; lua_getglobal(L, "f"); // 获取lua函数f lua_pushnumber(L, x); // 压入参数x和y lua_pushnumber(L, y); if(lua_pcall(L, 2, 1, 0) != 0) error(L, "error running functi

cocos2d-x 3.0 在C++中调用lua函数(2)

个人觉得3.0里面, 在C++下面调用lua函数很不方便, 所以就扩展了一个类, 继承自LuaStack, 代码和使用方式如下: #ifndef __CC_LUA_STACKEX_H_ #define __CC_LUA_STACKEX_H_ #include "CCLuaStack.h" NS_CC_BEGIN class LuaStackEx : public LuaStack { public: void call_script_fun(const char* fun) { exe

uLua学习之调用Lua函数(五)

前言 在我开始这个系列的第一篇文章中,我就提到了Lua脚本用来实现宿主脚本的配置性和扩展性.上节说到的调用外部Lua脚本就对应了它的两大特性之一的配置性,那么另一大特性如何来体现呢?这就要说我们今天的话题了:Lua函数.uLua插件是用来解决unity3d热更新的方案,在我们需要对宿主程序做一些局部逻辑上的修改时,Lua函数就变得至关重要.那么如何在uLua中来调用Lua函数呢,现在就来看看吧!我们将通过两个例子来了解如何调用Lua函数. 第一个例子 首先,这个例子的函数是非常简单的,所以我们就

C语言调用Lua函数

记得上学时,初中英文课本中,上网叫做surfing the internet,中文叫网上冲浪.那个时期,人们经常称互联网为赛博空间.如今工作了,大量的零碎时间用于上微博,知乎,QQ,这些碎片化的阅读让人读起来轻松,也能获取些粗浅的信息.然而它们是消耗时间的黑洞,时间就这样一分一秒地飞逝,年末的时候,知乎会告诉你回答了多少问题,阅读了相当于一部<红楼梦>那么多的文字.只是当你静下来一想,这些浅阅读并没给你带来有深度,系统的知识.在你的时间线上,两条相邻信息往往是八竿子也打不着的.而且你还时不时去

cocos2d-x 3.0 在C++中调用lua函数

代码用的是<cocos2d-x 3.0 在lua中调用自定义类>中的代码. 在上篇的基础上进行扩充. 写lua函数 local function process_packet(user_data) if user_data then user_data = tolua.cast(user_data, "user_data"); print (user_data:uid()); print (user_data:uname()); end end local ghall =

c++调用lua函数2中方式

http://my.oschina.net/kkkkkkkkkkkkk/blog/521496 上一篇 续集 .. 其中handler 通过手动改 tolua 生成的 cpp文件获取 .. void toLuaFunc::callLuaFunc(const char*ARG) { CC_ASSERT(handler > 0, "call lua func 's handle must bigger than 0"); /* 方法1   发送事件到lua cocos2d::Comm

C#调用LUA函数

using UnityEngine; using System.Collections; using LuaInterface; public class testLUACALL : MonoBehaviour { // Use this for initialization void Start () { LuaState S = new LuaState(); if (S == null) return; S.Start(); S.DoFile("test1.lua"); S.Do

C++调用JS,可变参模板实现,方便调用

#include "scripting/js-bindings/manual/ScriptingCore.h" #include <sstream> #include <type_traits> /// args push helper template<typename _Ty> inline void jsx_unpack_arg(std::stringstream& ss, int& carg, const _Ty& a

简述C/C++调用lua中实现的自定义函数

1.首先说下目的,为什么要这么做 ? 正式项目中,希望主程序尽量不做修改,于是使用C/C++完成功能的主干(即不需要经常变动的部分)用lua这类轻量级的解释性语言实现一些存在不确定性的功能逻辑:所以,程序功能如有问题,只需对lua脚本作出修改,而修改脚本的好处是简单高效,改完脚本后重新执行程序便能看到效果.  2.具体怎么做? 一般来说,C/C++调用lua接口或是数据交互,首先要做的是包含lua相关操作的头文件以及lua库相关的头文件,然后调用接口创建lua环境.用操作栈的规则和lua交互数据