Inspired by Rob, I decided I’d take a crack at embedding Lua scripting in a couple C++ projects that I’m working on. Rob has gone the ultimate route of using SWIG, but when I was starting to do some research, I stumbled upon Luabridge, a library that attempts to do all the interface binding using C++ templates. This sounds like more fun to me – even if I can’t later use it for Scheme scripts or whatever in the future.
Next it’s time to build Lua. I originally used Visual Studio .NET 2005 for this, so I went to Start > Program > Microsoft Visual Studio 2005 > Visual Studio Tools > Visual Studio 2005 Command Prompt. This is a command prompt window with all environment variables set up properly to compile and link from the command line. In this command prompt window, I went to c:\lua-5.1.2\ and typed: etc\luavs.bat. This invoked a batch file that built the Lua libraries. The files were plopped into c:\lua-5.1.2\src: lua51.dll and lua51.lib.
HOWEVER, later in the process, this ended up causing me no end of trouble. Specifically, when I later tried to link in the Lua DLL, I started getting run-time errors: “”The application has failed to start because MSVCR80.dll was not found.” I then did some cursory searching around the internet and found that I was not alone. There are several articles about this. I tried several solutions regarding the DLL manifest, but nothing seemed to solve my problem. One day I’ll really have to learn about DLL manifests and assemblies, but for now I just wanted to get this to work like it used to with VC7 and VC6. At one point, I even got so annoyed as to contemplate building KDE and KDevelop on Windows so I could use the same environment on Linux and Windows – but then I got a-hold of myself.
Ultimately, I downloaded MinGW and built the Lua libraries using the makefile:
- Ensure the MinGW executables are in your path. Either copy all .exe files to an executable path or add to your PATH environment variable in Windows (right-click My Computer > Properties > Advanced > Environment Variables > System Variables)
- In a new command prompt, cd to c:\lua-5.1.2\
- mingw32-make mingw
- Confirm the library files were built: lua51.lib will be sitting in c:\lua-5.1.2\src\ and lua51.dll will be sitting in c:\lua-5.1.2\mingw\
These build instructions are also in the INSTALL file if you need further reference.
Now that Lua is built, we’re going to install Luabridge, which allows us to cleanly talk between C++ and Lua. Go download the latest (0.2) from here. Then unzip the package (I used c:\ so it unrolled into c:\luabridge-0.2\).
We’re getting close now. Next, we’re going to build Luabridge. There are VC7 (.NET 2003) and VC8 (.NET 2005) projects included in the zip as well as the standard Makefile. I used the VC8 project, of course.
Open up the solution file and update both projects: Add c:\lua-5.1.2\etc\ and c:\lua-5.1.2\src\ to the include directories. Add c:\lua-5.1.2\src\ to the library paths. Add lua51.lib as a library dependency.
Now build the Luabridge project. You should see a libluabridge.lib (or libluabridged.lib for Debug) file get created in c:\luabridge-0.2\lib\.
To run the test project in the Luabridge solution, you will have to copy over the lua51.dll from c:\lua-5.1.2\src\ to the “test” project’s executable path. Now go to a command prompt, change directory to c:\luabridge-0.2 and type src\testd. You should see a “All tests succeeded” message. This proves that we’ve built Lua and Luabridge successfully.
Adding Lua and Luabridge To Your Game
Now is the last step – we’re going to integrate Lua with an existing C++ game or project using Luabridge. Since you’re now an expert on Visual Studio project configuration I’ll just breeze over the steps:
- Add the Lua and Luabridge header files into your include paths
- Add the library path to the Lua and Luabridge libraries
- Add lua51.lib and libluabridge.lib (libluabridged.lib for Debug) to your dependencies
- Copy the lua51.dll into your executable path (Luabridge does not require a DLL as it really only uses C++ template metaprogramming to achieve its ends)
An interesting note on Luabridge: In order to pass C++ objects to Lua using Luabridge, you can’t just send Foo* as an argument or a return value to a function. The reason is that the object pointed to by your Foo pointer might be deleted at some point in C++ land – yet Lua-land won’t know that and when it tries to access the object, it will cause problems (crashes). To help circumvent this, Luabridge requires that pointers to C++ objects be wrapped in a smart pointer, specifically a shared_ptr templated object. This ensures that as long as someone still has a reference to this pointer, the object will not be deleted.
You can use the minimal shared_ptr that comes with Luabridge, or you can use a different shared_ptr template that conforms to the Boost shared_ptr template. I recommend you use Boost’s version if you have the guts to download it, because it allows things like default creation of shared_ptr’s without assigning values (useful if you want to have a fixed array of objects, for instance). Here’s how I set up my C++ project to use Boost’s shared_ptr with Luabridge:
I’ll get into how you can actually code with Luabridge in a later blog post – once you’ve got it all linked in, it’s really not that hard.