LuaBind Introduction

The Lua Logo Lua is a great scripting language for games and regular applications alike because it is fast, simple and well suited for embedding (embedding means putting the scripting language into your application instead of making your application an add-on module to the scripting language). Lua can easily be compiled and setting up a lua environment in your code is no big task either, because all you have to do is call luaL_newstate() and later lua_close().

The Lua Logo However, when the time comes to create bindings for your functions and classes so scripts can call into your code, things quickly become harder. You’re forced to learn the semantics of the lua stack, what effects various functions of the lua API have on it, how lua treats user data and finally, you’ll have to repeat the tedious work of writing lua wrappers for your functions and classes again and again. LuaBind solves this problem nicely by automatically generating the wrapper code for any function or class you hand to LuaBind. Contrary to other lua wrapper generators, LuaBind works entirely in C++ and does not require any kind of special preprocessor.

Once LuaBind is set up and working, using Lua becomes as fun and easy as you always wanted it to be. This article will help you to reach that point and then shows you how to use it to call C/C++ functions from Lua, to call Lua functions from C++ and even to export entire C++ classes.

Getting your Hands on LuaBind Binaries

To use LuaBind, you have two options: Add all LuaBind sources to your project, or compile LuaBind into a static library which you can then link to your project. This article will follow the latter approach, because it is cleaner and you can more easily upgrade your projects to new versions of LuaBind.

To compile LuaBind, you would normally download the sources of Lua, Boost and LuaBind, set up and compile each library as well as possibly modify LuaBind due to changes in the Boost library which have not been reflected in LuaBind yet. Because this whole process can be somewhat troublesome, you can also download a single package containing precompiled binaries here:

Download

Download

Demonstration project with LuaBind binaries that compiles out-of-the-box in either Microsoft Visual C++ Express 2010 SP1 or one of the bigger Visual Studio editions.
Nuclex.LuaBind.Demo-0.9.1.7z (6.0 MiB)

Precompiled libraries and headers can be found in the Directory Icon References directory in case you want to use them in another project:

  • Directory Icon References
    • Directory Icon Lua (5.2.0)
    • Directory Icon LuaBind (0.9.1)
    • Directory Icon Boost (1.47.0, minimal subset)

Calling Lua Functions from C++

It doesn’t get any easier than this. To call a function in a lua script from C++, you can use LuaBind’s call_function() template function like this:

int main() {
  // Create a new lua state
  lua_State *myLuaState = luaL_newstate();

  // Connect LuaBind to this lua state
  luabind::open(myLuaState);

  // Define a lua function that we can call
  luaL_dostring(
    myLuaState,
    "function add(first, second)\n"
    "  return first + second\n"
    "end\n"
  );

  cout << "Result: "
       << luabind::call_function<int>(myLuaState, "add", 2, 3)
       << endl;

  lua_close(myLuaState);
}

Let’s see, first we use luabind::open() to connect the lua state to LuaBind. This has to be done for all lua states where we want to use LuaBind. Next, we execute some lua code so the lua state contains a global function named add(), which is then called in the cout line using luabind::call_function(). This template function requires the type of the return value to be passed in as a template parameter. Its first argument is the lua state that contains the lua function we’d like to call. The next argument denotes the name of that function and after that we can list any arguments that we want to pass to the lua function. The types of these additional arguments can be identified without our help because of the way templates work in C++.

Making C++ functions callable from Lua

The next example is a bit more complicated. We want to call a C++ function from a lua script. Instead of wasting our time with lua stack manipulation and data type conversion, we can simply do this:

void print_hello(int number) {
  cout << "hello world " << number << endl;
}

int main() {
  // Create a new lua state
  lua_State *myLuaState = luaL_newstate();

  // Connect LuaBind to this lua state
  luabind::open(myLuaState);

  // Add our function to the state's global scope
  luabind::module(myLuaState) [
    luabind::def("print_hello", print_hello)
  ];

  // Now call our function in a lua script
  luaL_dostring(
    myLuaState,
    "print_hello(123)\n"
  );

  lua_close(myLuaState);
}

As before, we need to connect LuaBind to the lua state by using luabind::open(). The luabind::module() part is required to tell LuaBind what scope we want to add our function to. Finally, using luabind::def() we can export a C/C++ function to the lua state. The first argument is the name as it will be seen in lua scripts, the second is the C/C++ function we want to export.

If you need to export multiple functions, you should seperate them from each other using commas (,). You’re not allowed to just end each definition with a semicolon because they’re still enclosed by the luabind::module statement.

Exporting Classes to Lua

Now onto the fun part. LuaBind allows you to export entire C++ classes to lua, including constructors with arguments, overloaded functions and even operators. It is just as well possible to use a lua class from within C++ through LuaBind. But let’s start with something simple:

class NumberPrinter {
  public:
    NumberPrinter(int number) :
      m_number(number) {}

    void print() {
      cout << m_number << endl;
    }

  private:
    int m_number;
};

int main() {
  // Create a new lua state
  lua_State *myLuaState = luaL_newstate();

  // Connect LuaBind to this lua state
  luabind::open(myLuaState);

  // Export our class with LuaBind
  luabind::module(myLuaState) [
    luabind::class_<NumberPrinter>("NumberPrinter")
      .def(luabind::constructor<int>())
      .def("print", &NumberPrinter::print)
  ];

  // Now use this class in a lua script
  luaL_dostring(
    myLuaState,
    "Print2000 = NumberPrinter(2000)\n"
    "Print2000:print()\n"
  );

  lua_close(myLuaState);
}

This might look difficult, but once you’ve got the idea, exporting other classes will be a no-brainer. The first thing to notice is luabind::class_, which is a template struct used to export classes to lua. The template argument we’re specifying is, of course, the class that we wish to export. Its normal constructor argument defines the name under which the class will be known in lua scripts. You’re actually creating a temporary, unnamed instance of a luabind::class_<NumberPrinter> on which methods can be called.

The methods we’re calling can be seen in the next two lines where the class constructor is exported (using a special auxiliary structure luabind::constructor) as well as the print method used to display the number. Notice that unlike exported functions, class methods are not seperated by commas, but as before mustn’t be terminated by a semicolon.

Exporting class attributes and properties

LuaBind can also export a class’ attributes (variables defined in a class) or even simulate a variable to lua by using the getter and setter methods in a class. To make it a bit more interesting, we’re going to export two C++ template structures now. The concept of templates does not exist in lua, so we can only register an actual class or in other words a template instanced to a specific type.

template<typename T>
struct Point {
  Point(T X, T Y) :
    X(X), Y(Y) {}

  T X, Y;
};

template<typename T>
struct Box {
  Box(Point<T> UpperLeft, Point<T> LowerRight) :
    UpperLeft(UpperLeft), LowerRight(LowerRight) {}

  Point UpperLeft, LowerRight;
};

int main() {
  // Create a new lua state
  lua_State *myLuaState = luaL_newstate();

  // Connect LuaBind to this lua state
  luabind::open(myLuaState);

  // Export our classes with LuaBind
  luabind::module(myLuaState) [
    luabind::class_<Point<float> >("Point")
      .def(luabind::constructor<float, float>())
      .def_readwrite("X", &Point<float>::X)
      .def_readwrite("Y", &Point<float>::Y),

    luabind::class_<Box<float> >("Box")
      .def(luabind::constructor

As you can see, the Lua script works perfectly with both classes, despite the fact that one is used within the other. The def_readwrite() method of luabind::class_ directly exports the point and box structure’s attributes and makes them available to the script. If all those template brackets are irritating you, there’s of course always the possibility to use a typedef instead!

You could now directly pass a Box or Point to a lua function you call through luabind::call_function() and it would work just the way you expect it to work.

More!

If you ever made a typo while working your way through this tutorial, you might have found yourself in front of an ugly run-time error message. This is due to the fact that luabind transforms lua errors into various exceptions, all derived from the common std::exception. If you wish to see a human-readable error message, a try..catch block has to be set up to catch std::exceptions!

We will now demonstrate this as well as explore some other useful parts of LuaBind:

struct ResourceManager {
  ResourceManager() :
    m_ResourceCount(0) {}

  void loadResource(const string &sFilename) {
    ++m_ResourceCount;
  }
  size_t getResourceCount() const {
    return m_ResourceCount;
  }

  size_t m_ResourceCount;
};

int main() {
  // Create a new lua state
  lua_State *myLuaState = luaL_newstate();

  // Connect LuaBind to this lua state
  luabind::open(myLuaState);

  // Export our class with LuaBind
  luabind::module(myLuaState) [
    luabind::class_<ResourceManager>("ResourceManager")
      .def("loadResource", &ResourceManager::loadResource)
      .property("ResourceCount", &ResourceManager::getResourceCount)
  ];

  try {
    ResourceManager MyResourceManager;

    // Assign MyResourceManager to a global in lua
    luabind::globals(myLuaState)["MyResourceManager"] = &MyResourceManager;

    // Execute a script to load some resources
    luaL_dostring(
      myLuaState,
      "MyResourceManager:loadResource(\"abc.res\")\n"
      "MyResourceManager:loadResource(\"xyz.res\")\n"
      "\n"
      "ResourceCount = MyResourceManager.ResourceCount\n"
    );

    // Read a global from the lua script
    size_t ResourceCount = luabind::object_cast(
      luabind::globals(myLuaState)["ResourceCount"]
    );
    cout << ResourceCount << endl;
  }
  catch(const std::exception &TheError) {
    cerr << TheError.what() << endl;
  }

  lua_close(myLuaState);
}

The .property() method of luabind::class_ emulates an attribute in the lua class through getter and (optionally) setter methods in C++. It is not only shorter, but also far more natural to write Items = X.ItemCount than to write Items = X:getItemCount(). The other feature this example introduces is luabind::globals() which returns the lua globals table (where all of a script’s functions and global variables are stored) wrapped up in a luabind::object. In this example, we’re accessing a global named ResourceCount, which we need to cast to an integer using luabind::object_cast<>().

This should be enough to get you up to speed with LuaBind. Experiment with the examples and then go read the LuaBind docs, they’re not even harder to read than this article ;)

There’s a lot more to LuaBind you can discover, like operator overloading, deriving classes from each other, read only properties, and more.

29 comments

  1. Thomas Brown says:

    Im having a lot of problems settings up lua bind and boost. I have linked the libraries, included the headers. When I run it I get lots of unhandled exceptions and luabind moaning at boost

  2. Cygon says:

    I take it you’re using Visual Studio 2010 and the demo application provided here at least works without any problems?

    It’s hard to tell what might be going wrong — have you tried catching those exceptions and looking at what the messages they carry say?
    Do you mean compiler warnings when you say LuaBind is moaning at Boost? Maybe I can tell more if you post the first 3 or so you’re getting!

  3. Brendan says:

    Thanks for this tutorial- it’s been very helpful, and the fact that you prepackaged the libraries is really awesome. Thank you!

  4. manoj says:

    excellent tutorial. i am new to lua. i want to call execute lua script from a file in my c++ program. in your first example, if the function add is placed in a separate file then how can it be called from main() function.

  5. Chris says:

    This tutorial is great, however, how do I get luabind to load a lua script file? Instead of typing lua in the string?

  6. Cygon says:

    Now it’s two of them ;-)

    This is pretty basic stuff you’re asking and it’s not even about LuaBind. I mean, come on, if the method for executing a string is called luaL_dostring(), what might the method for executing a file be called? Hint: luaL_dofile().

    Lua only has a handful of methods and its official documentation has a nice overview — if I search for “file” there, it takes me straight to dofile() and luaL_dofile().

  7. Chris says:

    Thanks for your reply. I had been very frustrated with several unrelated programming problems yesturday and this difficulty spilled over into this.

    I appreciate your help!

  8. Cygon says:

    No problem, I just asked a bit pointedly because the answer seemed so obvious :D

  9. Tom Davy says:

    Can you show what you header files you included? I’m having trouble just to even this program to even compile.

  10. Cygon says:

    There is a demo application available for download near the top of the article. It contains a LuaBindDemo.cpp that has all of the required headers included (so you could just copy & paste the sample code from this tutorial in there and compile – which is exactly what I’m doing each time I update the archive to verify the code snippets still work :p)

    I’m including the Lua and LuaBind headers like this:

    // Include the lua headers (the extern "C" is a requirement because we're
    // using C++ and lua has been compiled as C code)
    extern "C" {
      #include "lua.h"
      #include "lualib.h"
      #include "lauxlib.h"
    }
    
    // This is the only header we need to include for LuaBind to work
    #include "luabind/luabind.hpp"
    
  11. Chris says:

    Hey There,

    just started wrking with luabind, got a question about getting the output to my console with visual studio 2010.

    With normal lua it worked just fine, i did not need to edit anything within lua to get it outputing to the standard console, but with luabind nothing is sent to the output. I am using dofile rather than do string.

    I have wrapped the call in a try/catch and stepped through debugging and there are no errors with the call.

    ANy help would be great.

  12. Cygon says:

    It’s possible to redefine Lua’s print so that output gets sent wherever you want (a file, a list box in a GUI, etc.). On a lower level, stdout and stderr can also be redirected to achieve the same for any printf() and cout call.

    But to my knowledge, LuaBind does neither.

    You could try writing something to the console via std::cout and then repeat the same using luabind::call_function to see where the problem lies. Then move it to progressively earlier locations in your program until you can pinpoint where console output is being disabled/redirected.

  13. Chris says:

    I am unsure why this is happening, but I ended up redirecting print to cout for now.

    This does pose a problem for anything like print(45), I guess I can just create an overload for every possible print, I am not sure if there is another way around this.

  14. Cygon says:

    You can still try to isolate it step by step. First check if Lua’s print() still works normally right after you created the lua state, then right after luabind::open(), then after you’ve bound your modules with luabind etc.

    If replacing Lua’s print() method fixed the issue, it really sounds like luabind could be responsible (unless you’re using other libraries that integrated into Lua). I haven’t used luabind in my code since 0.2 versions ago :)

  15. Cam says:

    @Cygon, why don’t you use luabind anymore? What do you use instead?

  16. Cygon says:

    Mono. It has a very nice embedding API (http://www.mono-project.com/Embedding_Mono), and if you believe the programming language shootout, it’s almost 10 times faster than Lua.

    My primary motivation however is that I find it easier to stay with C-like languages and that .NET’S class library is very complete, whereas in Lua I find that I always have to add many things myself.

  17. Thomas says:

    Great tutorial Cygon. It was really helpful to get started. It’s not always easy to get started with new programming languages(I’ve been coding with C-like languages for a while now), but you’ve really saved me lots of trouble and the fact that you provided an “all in one” package is awesome. Thanks again!

  18. Mathias says:

    Hello Cygon,
    thank you very much for the great tutorial!
    I would like to build luabind with VS2012. Could you please publish the luabind package you used and maybe a short description how to build? I had some troubles with building luabind for Lua 5.2…
    Thanks!

  19. Cygon says:

    Check the package I provided for download near the top of the article. It contains not only the demo and binaries, but there’s a LibrarySources.7z inside that has the LuaBind, Lua and Boost sources I used (LuaBind has 3 or 4 minor tweaks to make it compile and Boost is trimmed to the minimal set of headers required to compile LuaBind on VS2010).

    I haven’t updated the package to VS2012 yet, but I think apart from Boost warning you about not knowing VS2012′s shiny new compiler, it should be possible to compile with VS2012, too.

  20. Mathias says:

    Thanks – this helped!

  21. priya says:

    best tutorial…i’ve ever seen

  22. Mahan says:

    Hi, Nice tutorial. I have question. Why luabind.lib has a large size? and in comparison to debug library, the release library is doubled in size. I now have 14mb luabind.release.lib. Is this because of boost? Thanks.

  23. Cygon says:

    That’s something that unfortunately happens with template-heavy code and static libraries. Your final executable won’t be bloated like that, but it may be inconvenient if you want to add the lib to source control.

    Workarounds would be to compile luabind as a DLL (which I expect will get the size of luabind.lib + luabind.dll to something like 100-200 KiB) or to add the luabind sources directly to your project instead of using the lib.

  24. Immortaldragon says:

    Great, but i can’t download Nuclex.LuaBind.Demo-0.9.1.7z
    Is it deleted?
    If so? could you please send me.
    And one more question: How can i overload __index or __newindex metamethod of metatable from luabind?

  25. Mahan says:

    Thanks for response. I’ve read that shared libraries for LuaBind have a problem with calling functions overloads at run-time and there should be a minor change in one of the source files to compare `typeid(f1) == typeid(f2)` instead of `typeid(f1).name == typeid(f2).name`. Anyway, thanks for these up to date libraries!

  26. Cygon says:

    @Immortaldragon: It’s still there, but a recent PHP update segfaults when looking up the file’s mime type for the HTTP headers. It’s fixed now, downloads should work again.

    I don’t know if there’s a built-in method to overload Lua’s indexer, the official docs don’t seen to even mention __index, but there’s this post on stackoverflow: How to bind a std::map to Lua with LuaBind (check the first answer, too, though, the snippet isn’t entirely correct)

  27. Mahan says:

    @Immortaldragon The post from Stackoverflow was asked by me. Before that answer, I couldn’t get it to work so I came up with an alternative approach. I used overloaded functions to achieve what I need. User now can write something like this in my Lua codes:

    player:scripts(‘movement’):properties(‘stat’, ‘stand’)
    print (player:scripts(‘movement’):properties(‘stat’))

    Here, scripts(‘movement’):properties is overloaded. One for getter and one for setter.

  28. ZachPrinz says:

    So if we have VS2012 we should be getting LNK2019 errors if we try to use the precompiled binaries that you provided in the References folder?

    If so, how do you build the binaries (or libraries, I’m not really sure what they’re called) again using the LibrarySources.7z file in the download you provided? Also what should we do with the patch files?

    By the way this tutorial is awesome. There are almost 0 tutorials on luabind (I’ve been looking for a while) and out of those none of them are good. This is the first one that has been well written and helpful.

  29. Havinsoul says:

    Hi,

    How do I get it works in Code::Blocks ? Is it possible to build LuaBind from this IDE ?

    Thank you.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Please copy the string yAbRZW to the field below:

Social Widgets powered by AB-WebLog.com.