使用C++调用 LUA 函数收藏

来源:互联网 发布:网约车软件开发 编辑:程序博客网 时间:2024/04/29 23:12

使用C++调用 LUA 函数收藏

新一篇: 在你的游戏中应用LUA | 旧一篇: 使用模板快速排序

Note:This is an unedited contribution. If this article is inappropriate,needs attention or copies someone else's work without reference thenplease Report This Article
  • You are signed up for one or more newsletters but your email address is either unconfirmed, or has not been reconfirmed in a long time. Please click here to have an email sent that will allow us to confirm your email address and start sending you newsletters again.
  • Download source code - 538.1 Kb

Audience

This article was written for C++ developers that want extend your application with Lua programming Language.

Introduction

One of the most common tasks when you use Lua in C++ application iscall Lua functions, but this can be tiresome, you need use a lot offunctions of LUA C API (lua_getglobal, lua_pushnumber, lua_pushstring,lua_tointeger and so on) to call one simple Lua function. Here I willshow C++ templates that can make your life easy.

Interface

The interface is very easy see:. Think that you have these four Lua function and you want to call in your application:

Listing 1 – Lua Functions – test.lua
--------------------------------------------------------------------------------------

var = 10;

function sum4(a, b, c, d)

      return a+b+c+d;

end

function catenate(a, b)

      return a.." and "..b;

end

function incVar(value)

      var = var+value;

end

function getVar()

      return var;

end

--------------------------------------------------------------------------------------

Then what you need to call these function is use:

  • LuaCall template class.

The basic way are you instantiate LuaCall with types of your Lua function receive and return, for sample:

Collapse
float a = LuaCall<float, int, float, int, int>(L, "sum4").call(5, 1.5, 5, 5); 
See complete sample below (listing 2).

Listing 2 – using LuaCall – main.cpp

--------------------------------------------------------------------------------------

#include <iostream>

#include "LuaCall.h"

extern "C" {

#include <lua.h>

#include <lauxlib.h>

#include <lualib.h>

}

int main()

{

try

{    

      lua_State *L;

      L = luaL_newstate();

      if(luaL_loadfile(L, "list1.lua") || lua_pcall(L, 0, 0, 0))

{

            throw std::string(std::string(lua_tostring(L, -1)));

      }

           

      std::cout << LuaCall<float, int, float, int, int>(L, "sum4").call(5, 1.5, 5, 5) << std::endl;

      std::cout << LuaCall<std::string, std::string, std::string>(L, "catenate").call("Renato", "Bianca") << std::endl;

      LuaCall<NullT, int>(L, "incVar").call(10);

      std::cout << LuaCall<int>(L, "getVar").call() << std::endl;

           

      if(L != NULL)

      {

            lua_close(L);

      }

}

catch (const std::string &e)

{

      std::cout << e << std::endl;

}

      return 0;

}

Implementation

This is the implementation of LuaCall:

Listing 3 –LuaCall imp – LuaCall.h

--------------------------------------------------------------------------------------

template <

typename T1,

typename T2

>

class  Duo

{

};

// type that represents unused type parameters

class  NullT

{

};

class LuaCallBase

{

public:

      LuaCallBase(lua_State *luaState, const std::string& functionName)

      {

            L = luaState;

            lua_getglobal(L, functionName.c_str());

      }

protected:

      void push(const int &value)

      {

            lua_pushinteger(L, value);

      }

      void push(const float &value)

      {

            lua_pushnumber(L, value);

      }

      void push(const double &value)

      {

            lua_pushnumber(L, value);

      }

      void push(const std::string &value)

      {

            lua_pushstring(L, value.c_str());

      }

      void get(int &value) const

      {

            value = lua_tointeger(L, -1);

      }

      void get(float &value) const

      {

            value = lua_tonumber(L, -1);

      }

      void get(double &value) const

      {

            value = lua_tonumber(L, -1);

      }

      void get(std::string &value) const

      {

             value = (char*)lua_tostring(L, -1);

      }

      void get(NullT &value) const

      {

      }

protected:

      lua_State *L;

};

template <

typename TR,

typename T1 = NullT,

typename T2 = NullT,

typename T3 = NullT,

typename T4 = NullT

>

class  LuaCall

      : public Duo<TR, typename LuaCall<T1,T2,T3,T4,NullT> >

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1, T2 a2, T3 a3, T4 a4)

      {

            TR returnValue;

            push(a1);

            push(a2);

            push(a3);

            push(a4);

            if(lua_pcall(L, 4, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <

typename TR,

typename T1,

typename T2,

typename T3

>

class  LuaCall<TR,T1,T2,T3,NullT>

      : public Duo<TR,T1>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1, T2 a2, T3 a3)

      {

            TR returnValue;

            push(a1);

            push(a2);

            push(a3);

            if(lua_pcall(L, 3, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <

typename TR,

typename T1,

typename T2

>

class  LuaCall<TR,T1,T2,NullT,NullT>

      : public Duo<TR,T1>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1, T2 a2)

      {

            TR returnValue;

            push(a1);

            push(a2);

            if(lua_pcall(L, 2, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <

typename TR,

typename T1

>

class  LuaCall<TR,T1,NullT,NullT,NullT>

      : public Duo<TR,T1>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1)

      {

            TR returnValue;

            push(a1);

            if(lua_pcall(L, 1, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <typename TR>

class  LuaCall<TR,NullT,NullT,NullT,NullT>

      : public Duo<TR,NullT>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(void)

      {

            TR returnValue;

            if(lua_pcall(L, 0, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <>

class  LuaCall<NullT,NullT,NullT,NullT,NullT>

      : public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      void call(void)

      {

            if(lua_pcall(L, 0, 0, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

      }

};

原创粉丝点击