65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C++ 语言调用 Lua 函数。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (15投票s)

2007年2月2日

MIT

5分钟阅读

viewsIcon

50753

downloadIcon

758

使用 C++ 语言调用 Lua 函数。

目标读者

本文面向希望使用 Lua 编程语言扩展应用程序的 C++ 开发者。

引言

在 C++ 应用程序中使用 Lua 时,最常见的任务之一是调用 Lua 函数,但这可能很繁琐。您需要使用 Lua C API 的许多函数(lua_getglobal、lua_pushnumber、lua_pushstring、lua_tointeger 等)才能调用一个简单的 Lua 函数。在这里,我将展示可以简化您操作的 C++ 模板。

接口

接口非常简单,请看:假设您有这四个 Lua 函数,并且希望在您的应用程序中调用它们

列表 1 – Lua 函数 – 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

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

那么,要调用这些函数,您需要使用

  • LuaCall 模板类。

基本方法是使用 Lua 函数接收和返回的类型来实例化 LuaCall,例如

float a = LuaCall<float, int, float, int, int>(L, "sum4").call(5, 1.5, 5, 5); 
请参阅下面的完整示例(列表 2)。

列表 2 – 使用 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)));

            }

      }

};

Bibliography
Roberto Ierusalimschy
Programming in Lua – 2nd ed. (http://www.inf.puc-rio.br/~roberto/pil2/)
ISBN 85-903798-2-5

David Vandevoorde - Nicolai M. Josuttis
C++ Templates - The Complete Guide
ISBN 0-201-73484-2
Lua.org
https://lua.ac.cn/
Mailing list
https://lua.ac.cn/lua-l.html
Community
https://lua.ac.cn/community.html
Embeddable scripting with Lua
http://www-128.ibm.com/developerworks/linux/library/l-lua.html
The Web Links listed here may not be valid in the future.
使用 C++ 语言调用 Lua 函数。- CodeProject - 代码之家
© . All rights reserved.