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

Calling Lua functions : using C++ language.

, 2 Feb 2007
Rate this:
Please Sign up or sign in to vote.
Calling Lua functions : using C++ language.

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

Share

About the Author

Renato Tegon Forti
Systems Engineer
Brazil Brazil
No Biography provided

Comments and Discussions

 
Questionhelp Pinmembersteven84414-Jun-13 17:32 
Generalwell done! [modified] Pinmemberdled30-Aug-12 8:18 
GeneralRe: well done! PinmemberRenato Tegon Forti4-Sep-12 3:15 
GeneralNice. PinmemberCrusiatus Black13-Nov-08 1:43 
GeneralLooks good ... PinmemberSceptic Mole3-Feb-07 1:15 
GeneralRe: Looks good ... PinmemberRenato T Forti3-Feb-07 4:27 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

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