Audience
This article was written for C++ developers that want extend your application with Lua programming Language.
这篇文章是为那些想用Lua语言扩展应用程序的C++程序员而写。
Introduction
One of the most common tasks when you use Lua in C++ application is call Lua functions, but this can be tiresome, you need use a lot of functions of LUA C API (lua_getglobal, lua_pushnumber, lua_pushstring, lua_tointeger and so on) to call one simple Lua function. Here I will show C++ templates that can make your life easy.
调用Lua函数是在C++应用程序中使用Lua最常见的任务之一。这个工作很烦人。你需要使用许多LUA C API(lua_getglobal, lu_pushnumber, lua_pushstring, lua_tointeger等等)来调用一个简单的Lua函数。在这里,我会展示让你的工作变得轻松的C++模板。
Interface
The interface is very easy see:. Think that you have these four Lua function and you want to call in your application:
这个接口很容易明白:想想你有下面4个Lua函数,你想在你的应用程序中调用他们。
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:
基本的方法是你用你的Lua函数的参数和返回值的类型实例化LuaCall模板,比如:
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:
这是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
http://www.lua.org/
Mailing list
http://www.lua.org/lua-l.html
Community
http://www.lua.org/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.
License
This article, along with any associated source code and files, is licensed under The MIT License
原文地址
http://www.codeproject.com/Articles/17469/Calling-Lua-functions-using-C-language