[luabind] Lua-cxx - C++11 APIs for creating Lua modules
Brought to you by:
arvidn,
daniel_wallin
From: Aaron F. <da...@gm...> - 2014-05-28 23:54:02
|
Hello! I would like to share Lua-cxx, a MIT-licensed project that I wrote that aids in writing modules and bindings for Lua. I posted this to the Lua mailing list, but I figured those who use Luabind would be interested to see another C++ take on Lua's API, so I decided to post here as well. :) Compared to Luabind, Lua-cxx is lower-level. Lua-cxx does not introduce an object model for Lua, nor does it use Luabind's policy model for arguments. It does use templates widely, including those features like variadic templates added in C++11, to provide a similar level of expressive power as Luabind. Lua-cxx, like Luabind, doesn't provide a complete façade over Lua's C API. On the contrary, I find Lua's C API to be amazingly well-designed, so I've tried to ensure that Lua-cxx can be intermixed freely with Lua's C API. In fact, most of the Lua C API has no analog in Lua-cxx - I just use the original. ;) // Add all arguments int add_several(lua::state* const state) { // Get each argument int sum = 0; for (int i = 1; i <= lua_gettop(state); ++i) { sum += lua::get<int>(state, i); } // Return the value lua::push(state, sum); lua_replace(state, 1); return 1; } That being said, there are several places where Lua-cxx greatly simplify common tasks. For instance, Lua has a number of lua_push* functions that can be replaced with Lua-cxx's lua::push template and appropriate specializations. You can extend this specialization with your own types, and Lua-cxx's other features will immediately support them. C++11 added variadic templates, which can be used to provide a way to push a function of any arity into Lua without needing to write the marshalling code yourself or running a preprocessor: // Standard C API is, of course, supported int create_foo(lua::state* const); lua::push(state, create_foo); // Fundamental types work, too int sum(int a, int b); lua::push(state, sum); // As are pointers to userdata and conversions to C++ strings. void changeTitle(QWindow* window, const std::string& title); lua::push(state, changeTitle); // Even lambdas work too, with a bit of help lua::push_function< int(int, int) >(state, [](int first, int second) { return first + second; }); Beyond this, Lua-cxx also has out-of-the-box support for Qt's QObject model, as well as rudimentary support for Gtk's GObject model, so you can push these types and their properties and methods will automatically be exposed to Lua. You can then specialize further on a specific subtype to add behavior not provided by that library's metadata. Here's a simple example of what can be done: // Create a new Lua environment to play with. auto env = lua::create(); // Introduce a global into Lua env["foo"] = "No time"; // Run some Lua code directly lua::run_string("assert(foo == 'No time')"); // Retrieve a global auto value = env["foo"].get<std::string>(); And here's another, more complex variant that shows how a Lua module for Qt's QWindow class could be created: #include <luacxx/stack.hpp> #include <luacxx/type/standard.hpp> #include <luacxx/type/function.hpp> #include <QWindow> int QWindow_new(lua::state* const state) { if (lua_gettop(state) > 1) { auto parent = lua::get<QObject*>(state, 2); lua_settop(state, 0); if (parent) { if (parent->inherits("QWindow")) { lua::make<QWindow>(state, static_cast<QWindow*>(parent)); } else { lua::make<QWindow>(state, static_cast<QScreen*>(parent)); } return 1; } // Otherwise, fall through } // Create a QWindow within Lua lua::make<QWindow>(state, static_cast<QWindow*>(nullptr)); return 1; } int luaopen_QWindow(lua::state* const state) { lua::thread env(state); env["QWindow"] = lua::value::table; env["QWindow"]["new"] = QWindow_new; return 1; } // Within Lua require "QWindow"; local window = QWindow:new(); window.width = 300; window.height = 300; window.title = "Hello, world"; window:show(); I've tried to document it well and keep things tidy. The source in total is almost 7,000 lines including documentation and unit tests. The documentation for each file can be formatted for easier viewing using the tiny bash script called cpod. It's in ./src. It just does a few regexes to make the source look like perldoc and calls that, so you'll need that too. Thanks for reading; I hope you take a look! The documentation in src/stack.hpp or perhaps the unit tests in src/tests/core.cpp are good first places to start. https://github.com/dafrito/lua-cxx.git -- Aaron -- Aaron Faanes <da...@gm...> |