[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: request for interest/participants: another lua C++ binding
- From: Chris Marrin <chris@...>
- Date: Fri, 07 Apr 2006 15:28:37 -0700
Oliver Schoenborn wrote:
Hello, I'm somewhat unhappy with the existing bindings to C++. The major
ones
* lua++: clean and simple, but requires custom lua
* cpplua: some good ideas, but some less good, and doesn't seem to
be maintained
* luabind: most powerful, but requires boost, and syntax a little
unnatural (IMO)
* swig and tolua++: don't allow for variable argument lists (AFAICT)
or for logging callbacks and gets/sets
I have had to use basic lua binding to C for on-the-job projects, and
I'm thinking that because of the above, perhaps yet another C++
alternative that has the following characteristics might fill a need:
* no dependency on boost
* usable with any lua (esp core dist)
* combines the best of cpplua, lua++ and luabind, without
necessarily going as far as luabind, remains usable if some parts
are dealt with swig
* basically hides all notion of stack (user wouldn't have to know
there is one)
* support logging of callbacks and sets/gets
Any comments on the above would be greatly appreciated (e.g., maybe such
a binding already exists?).
The idea is to host it on SourceForge (e.g.), it would be great to have
lua users involved (with more experience that I do, e.g. on stack use
and patterns of communication between C++ and lua interpreter).
Examples of use:
void func(const LuaArgs& args) {
if (args.size() < 1)
{
LuaLog(err, "error message");
return; // automatically causes return 0 to Lua
}
if (args[2]) // do something with args[2]
...
luaLog(trace, "func() called");
LuaObject a("a"); // will be "nil" if doesn't exist
int aa = a; // auto convert to int, or throw if can't
int bb = (a.nil() ? 0 : a); // won't throw, don't care if error
std::string sa = a; // converts to string? or throws?
// automatically pushes appropriate lua types onto stack
// and handles return value count
luaReturn("aString", aFloat);
}
int main()
{
LuaInterpreter lua;
lua.newLog(trace, stuff); // use lua code to implement this?
lua.newTable("ns");
lua.register("ns.func", func); // will be wrapped so LuaReturn works
LuaObject a = lua.newValue("a", 1); // let C++ compiler determine type
lua.doString("ns.func(2)");
lua.doFile("file.lua"); // may call ns.func()
}
The log functionality needs a fair bit of thinking but want it to be
simple to use.
You might want to see what I did in fusion, which is a piece of Emma
(http://emma3d.org). It is much simpler than the other solutions out
there. For instance, to make a C++ object that is accessible to Lua you go:
class MyClass : public Fusion::Object {
...
DECLARE_CLASS(MyClass, Object);
}
To add a prototype for this class of object you simply go:
engine->setProperty("MyClass", MyClass::newClassObject());
where engine is an instance of the Fusion::Engine class, essentially a
wrapper around the Lua interpreter.
Every class has an initializeClass() method which is used to expose
things to Lua. For instance, if your class has a member function like this:
double toNumber(const String& s) { return (double) s; }
you would add the following to initializeClass:
registerFunction("toNumber", &MyClass::toNumber);
In Lua you would go:
local c = MyClass()
local n = c:toNumber("12345")
Fusion takes care of getting values from the stack, type conversion and
pushing the result onto the stack. It does all this through the use of
static template functions to "thunk" between Lua and C++. ALl this is
hidden from the C++ programmer. The above is all that is needed.
Fusion also has a couple of classes which wrap the Lua stack. The Args
object is merely a wrapper around the stack itself. And Value is a
wrapper around values in the stack. You can do things like:
int someFunc(lua_State* L)
{
// stack: self
Args args(L);
args.push("to");
args.push("Number");
args.concat(2);
args.pushTable(1);
args.push(12.7);
args.call(1,1);
Value val = args[-1];
args.pop();
double d = Value.getNumber();
return 0;
}
Or the Engine and Object classes can hide the stack entirely. You can go
(assuming 'obj' is an object of type MyClass):
Value retval;
obj->callProperty("toNumber", retval, "12345");
double d = retval.getNumber();
It is a nice little package which links to a dll of around 176K on
win32. It has no dependencies other than Lua and is designed for Lua 5.1.
When I get the chance I will release this as a package and do better
docs. But please use or leverage it as you see fit...
--
chris marrin ,""$,
chris@marrin.com b` $ ,,.
mP b' , 1$'
,.` ,b` ,` :$$'
,|` mP ,` ,mm
,b" b" ,` ,mm m$$ ,m ,`P$$
m$` ,b` .` ,mm ,'|$P ,|"1$` ,b$P ,` :$1
b$` ,$: :,`` |$$ ,` $$` ,|` ,$$,,`"$$ .` :$|
b$| _m$`,:` :$1 ,` ,$Pm|` ` :$$,..;"' |$:
P$b, _;b$$b$1" |$$ ,` ,$$" ``' $$
```"```'" `"` `""` ""` ,P`
"As a general rule,don't solve puzzles that open portals to Hell"'