glob2-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[glob2-devel] Lua alongside USL


From: Bradley Arsenault
Subject: [glob2-devel] Lua alongside USL
Date: Sat, 8 Aug 2009 18:03:33 -0400

During my work on GunPunks, I have created a class that wraps Lua, called LuaScript. While many many of such libraries exist, I find my class unique because it is simple. It doesn't add unnecessary things like trying to automatically wrap exact C++ interfaces or create a fake object-oriented environment inside Lua. It merely wraps all of the tedious Lua code that one has to write to embed Lua. I think that Lua could be used as an alternative to USL, since the scripting system in Globulation 2 allows the use of different languages (although the menu's do not yet allow for this, this can be easily changed).

I'm willing to take a break from my work on GunPunks to implement Lua scripting in Globulation 2 as an alternative to USL, but leaving USL as the default and de-facto language, if people agree with this decision.

The class I have created for GunPunks merely loads a lua script file, and allows for C++ tie ins by calling functions like this:

    template<typename T> void registerFunctionCall0(const std::string& name, T* object);
    template<typename T, typename arg1> void registerFunctionCall1(const std::string& name, T* object);
    template<typename T, typename arg1, typename arg2> void registerFunctionCall2(const std::string& name, T* object);
    template<typename T, typename arg1, typename arg2, typename arg3> void registerFunctionCall3(const std::string& name, T* object);
etc...

When Lua calls a function registered in C++, it calls T::recieveLuaFunctionCall(const std::string& name, std::vector<boost::any>& arguments, LuaScript* script) with the given object.

You call Lua functions like so:

    boost::any executeLuaFunction(const std::string& function);
    boost::any executeLuaFunction(const std::string& function, boost::any arg);
    boost::any executeLuaFunction(const std::string& function, boost::any arg1, boost::any arg2);
etc...

boost::any is used extensively in the interface to allow for easy interoperability, although at the expense of type safety, but type safety goes out the window when you deal with scripts anyhow. The Lua system does make sure that the arguments passed into C++ functions have the correct types (the ones given as template parameters to the registerFunctionCall functions), so its not really lacking type safety. There is a version of registerFunctionCall that simply registers a function leaving it up to the user code to make sure the number and types of arguments are correct. This is particularly useful for functions that can accept different types.

The documentation specifies what values are acceptable and unacceptable for the boost::any values when calling Lua code from C++. Currently, you can send all of your basic POD typed to lua (int, unsigned int, long, unsigned char and all variations), as well as char* strings and std::string strings. I haven't found any need for more then this. You can register custom types (pointers only) via the following function:

    template<typename T> void registerLuaType(const std::string& name);

This allows the Lua code to be able to handle custom types. In terms of what Lua returns from functions ( or gives as function arguments when called C++ code ), Lua only has a few native types, so it sends either bool, std::string, or float inside the boost::any (or the custom registered pointers), and this is also specified in the documentation.

Some people I have talked to suggested using boost::variant rather then boost::any, however this would not allow arbitrary user types to be added into the system.

I'm currently working on adding the ability to put the functions into modules, so you call them inside Lua like "GUI.runMessageBox" rather then compounding it into one function name like "gui_runMessageBox", along with various efficieny improvements, so the interface I discussed here is likely to be expanded somewhat.

The current convention is for every class that wants to interact with lua, it has a function called  void prepareLuaForAccess(LuaScript& script), which calls all of the registerFunctionCall and setGlobalValues that it needs to, however this isn't a detail of the LuaScript class, just a convention I've been using in my own code.

In my experience, this class has been extremely useful. It was among the first things I created for Gun Punks, and it makes it very simple and direct to wrap Lua Scripts. You specifiy what functions are in the interface, and you add the code to responds to them. No troubling lua code or strange interfaces caused by things like tolua++.

--
Extra cheese comes at a cost. Bradley Arsenault.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]