[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Using templates to make a type-safe Lua wrapper for C++ objects
- From: Alex Ames <alexander.ames+lua@...>
- Date: Fri, 29 Jul 2011 06:38:46 -0700
A while back I started working on a C++ project and decided that I
wanted to use Lua to script elements of it. I didn't like LuaBind (it
seemed very heavyweight, it had some unusual syntax and quirks, and it
relies on boost). What I really wanted was something much more light
weight that just provided type-safe lua_push*, lua_to*, etc.
I couldn't find a library like that, so I decided to build it myself.
I've posted it a few places for feed back and a few people suggested I
put it up here for people to see and add it to the lua users wiki.
It's a single header with almost no dependencies, just the Lua headers
and iostream (and iostream can probably be removed. I'm thinking about
the best way to do that). The library can be found here:
https://bitbucket.org/alexames/luawrapper
There's documentation in the header itself as well as the README, but
the basic idea is you call luaW_register<Widget>(L, "Widget",
widget_table, widget_metatable, widget_extends); which creates a
Widget table in Lua. The Widget table automatically has the function
Widget.new() for making new Widget userdata objects. The Widget table
also contains any functions you added to widget_table, just like a
normal library. The objects themselves are given a metatable
containing everything in widget_metatable. And if you want to have
inheritance, like have Widgets extend Foo, you can create a null
terminated array of const char*s containing the name of each table you
want to extend (they need to be registered before you can extend
them). Widgets now have access to all the functions in the Foo
metatable (this is only a safe thing to do if the widget class
actually inherits from Foo though).
On the C++ side of things, you now have access to luaW_push<Widget>,
luaW_to<Widget>, luaW_is<Widget>, and luaW_check<Widget>, which act
just like you'd expect. They try their best to be type-safe (They only get
messed up if you manually go in and mess stuff, in which case you're
asking for trouble). It also works fine with shared_ptrs and the like, if you
registered shared_ptr<Widget>, you can use
luaW_push<Shared_ptr<Widget> >. This allows you to use your smart_ptrs
in lua and not have them cleaned up by the garbage collector if
there's still references to them in your C++ code.
It also handles various edge cases, like if you need to allocate
objects a certain way (such when there's no default allocator and you
can only get new objects through some kind of factory), or when you
have reference counted smart pointers that can't be uniquely
identified by their address (as a single object might be represented
by more than one smart pointer). Most of the details are outlined in
the readme I've been using this in my own projects for a while now and
it makes it so much nicer to work with C++ objects. I can make Lua
interfaces to my C++ libraries in no time (if you poke around on my
bit bucket page, you can even see that I have a bunch of vim snipmate
snippets set up in my vimrc folder that handle writing my C++/Lua
wrappers).
I'm putting this out into the wild to see if anyone else finds it
useful or has any feedback.
Thanks,
Alex