Click here to Skip to main content
Click here to Skip to main content

Calling Lua functions : using C++ language.

By , 2 Feb 2007
 

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 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.

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:

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

            }

      }

};

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

About the Author

Renato Tegon Forti
Systems Engineer
Brazil Brazil
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalwell done! [modified]memberdled30 Aug '12 - 8:18 
GeneralRe: well done!memberRenato Tegon Forti4 Sep '12 - 3:15 
GeneralNice.memberCrusiatus Black13 Nov '08 - 1:43 
GeneralLooks good ...memberSceptic Mole3 Feb '07 - 1:15 
GeneralRe: Looks good ...memberRenato T Forti3 Feb '07 - 4:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 2 Feb 2007
Article Copyright 2007 by Renato Tegon Forti
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid