Quantcast

Lua-cxx - C++11 APIs for creating Lua modules

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Lua-cxx - C++11 APIs for creating Lua modules

Aaron Faanes
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.


-- Aaron

--
Aaron Faanes <[hidden email]>

------------------------------------------------------------------------------
Time is money. Stop wasting it! Get your web API in 5 minutes.
www.restlet.com/download
http://p.sf.net/sfu/restlet
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Lua-cxx - C++11 APIs for creating Lua modules

Rodrigo (a.k.a. Skhaz)
awesome!
really a great job! I'll port my project that use luabind to lua-cxx soon

http://www.nullonerror.org/
-- flipping bits whilst updating pixels


On Wed, May 28, 2014 at 8:53 PM, Aaron Faanes <[hidden email]> wrote:

> 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 <[hidden email]>
>
> ------------------------------------------------------------------------------
> Time is money. Stop wasting it! Get your web API in 5 minutes.
> www.restlet.com/download
> http://p.sf.net/sfu/restlet
> _______________________________________________
> luabind-user mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/luabind-user
>

------------------------------------------------------------------------------
Time is money. Stop wasting it! Get your web API in 5 minutes.
www.restlet.com/download
http://p.sf.net/sfu/restlet
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Loading...