request for interest/participants: another lua C++ binding

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

request for interest/participants: another lua C++ binding

Oliver Schoenborn-2
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.

Any feedback or ideas about things missing from the three libraries
(lua++, luabind, cpplua) would be appreciated.

Thanks,
Oliver


Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Tyranni
Oliver,

>    * luabind: most powerful, but requires boost, and syntax a little
>      unnatural (IMO)

What is your specific issue with using boost?

Also, I use luabind not just as a binding system, but also to abstract dealing with the Lua stack.
The luabind::object class and luabind::object_cast functions are extremely useful for this:

double d = luabind::object_cast<double>( luabind::globals(L)['my']['nested']['table']['entry'] );
// yes that looks sorta ugly but in practice you don't write it like that


>    * swig and tolua++: don't allow for variable argument lists (AFAICT)
>      or for logging callbacks and gets/sets

SWIG supports C varargs.  I don't think it supports Lua varargs since the Lua-SWIG module is
targeted to Lua 5.0.  You can add it and send them patches.

In terms of adding logging functionality, there is complete flexibility in SWIG through the use of
typemaps.  They are a bit of a pain to use (you normally don't have to), but you can.

One problem with SWIG is that it is one-way... you can only access C++ objects and functions from
Lua.  You cannot (easily) get those objects back in C++.  [Something like this could be possible
with some adapating tools that combine SWIG and luabind.]


I'm not trying to squash your call to arms; I'm just trying to give you more info.

-Evan


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.
>
> Any feedback or ideas about things missing from the three libraries
> (lua++, luabind, cpplua) would be appreciated.
>
> Thanks,
> Oliver
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Matt Campbell-2
In reply to this post by Oliver Schoenborn-2
Hello Olver:

Your sample code looks nice, except for one fundamental problem.  It
assumes either a single, global Lua state, or something less portable
such as thread-local storage (which I use in my current Windows-only
project).

I would suggest adding "LuaInterpreter& L" as the first argument to
registered functions, and changing the current global utility functions
such as luaReturn to LuaInterpreter methods.  This way, your C++ binding
framework would support multiple Lua states in a portable way.

--
Matt Campbell
Lead Programmer
Serotek Corporation
www.freedombox.info
"The Accessibility Anywhere People"

Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Chris Marrin
In reply to this post by Tyranni
Tyranni wrote:
> ...
> What is your specific issue with using boost?

Boost is huge and poorly designed, so you can't separate out one piece
of it. That is my problem with it, at least!

--
chris marrin                ,""$,
[hidden email]          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"'
Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Javier Guerra Giraldez
In reply to this post by Matt Campbell-2
On Friday 07 April 2006 1:48 pm, Matt Campbell wrote:
> I would suggest adding "LuaInterpreter& L" as the first argument to
> registered functions, and changing the current global utility functions
> such as luaReturn to LuaInterpreter methods.  This way, your C++ binding
> framework would support multiple Lua states in a portable way.

i think the LuaArgs object could have a reference to the LuaInterpreter
object; if you need it, just call an accessor method.

also, the luaReturn in particular could be a macro (so it can do a full
return), but should get a reference either to the LuaInterpreter object or
the LuaArgs (and therefore to the LuaInterpreter itself).


--
Javier

attachment0 (207 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Chris Marrin
In reply to this post by Oliver Schoenborn-2
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                ,""$,
[hidden email]          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"'
Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Oliver Schoenborn-2
In reply to this post by Tyranni
Hi Tyranni,

Tyranni wrote:
> Oliver,
>
>  
>>    * luabind: most powerful, but requires boost, and syntax a little
>>      unnatural (IMO)
>>    
>
> What is your specific issue with using boost?
>  
My only problem with it is that many projects can afford to depend on it
due to size or other constraints.

> Also, I use luabind not just as a binding system, but also to abstract dealing with the Lua stack.
> The luabind::object class and luabind::object_cast functions are extremely useful for this:
>
> double d = luabind::object_cast<double>( luabind::globals(L)['my']['nested']['table']['entry'] );
> // yes that looks sorta ugly but in practice you don't write it like that
>  
Seems to me this casting could be handled automatically by the compiler.
As to the table example, is the above necessary? I would much prefer
being able to write

double d = luabind::globals(L, "my.nested.table.entry");

Seems rather simpler. Perhaps I don't know luabind enough, but in
general (from the docs) I find it forces you to be much more verbose and
explicit than necessary about what you want to achieve.
>  
>>    * swig and tolua++: don't allow for variable argument lists (AFAICT)
>>      or for logging callbacks and gets/sets
>>    
>
> SWIG supports C varargs.  I don't think it supports Lua varargs since the Lua-SWIG module is
> targeted to Lua 5.0.  You can add it and send them patches.
>  
Varargs don't preserve type and UDT.
> In terms of adding logging functionality, there is complete flexibility in SWIG through the use of
> typemaps.  They are a bit of a pain to use (you normally don't have to), but you can.
>  
I'd rather avoid having to use them, especially to support logging.
> One problem with SWIG is that it is one-way... you can only access C++ objects and functions from
> Lua.  You cannot (easily) get those objects back in C++.  [Something like this could be possible
> with some adapating tools that combine SWIG and luabind.]
>  
IIRC (though I might be thinking of tolua++ rather than SWIG), swig
allows you to "export" globals to lua interpreter, which address *some*
of the above, but you're right, it's doesn't help with getting things
from the lua interpreter.
> I'm not trying to squash your call to arms; I'm just trying to give you more info.
>  
I greatly appreciate your input, thanks for taking the time. Cheers,
Oliver

> -Evan
>
>
> 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
>>
>> [...]
>>    


Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Oliver Schoenborn-2
In reply to this post by Matt Campbell-2
Matt Campbell wrote:

> Hello Olver:
>
> Your sample code looks nice, except for one fundamental problem.  It
> assumes either a single, global Lua state, or something less portable
> such as thread-local storage (which I use in my current Windows-only
> project).
>
> I would suggest adding "LuaInterpreter& L" as the first argument to
> registered functions, and changing the current global utility
> functions such as luaReturn to LuaInterpreter methods.  This way, your
> C++ binding framework would support multiple Lua states in a portable
> way.
>
Yes, an important consideration, and there are ways to "keep it out of
the way" but make it available if necessary (see next post). Thanks for
the feedback.
Oliver


Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Oliver Schoenborn-2
In reply to this post by Javier Guerra Giraldez
Javier Guerra wrote:

> On Friday 07 April 2006 1:48 pm, Matt Campbell wrote:
>  
>> I would suggest adding "LuaInterpreter& L" as the first argument to
>> registered functions, and changing the current global utility functions
>> such as luaReturn to LuaInterpreter methods.  This way, your C++ binding
>> framework would support multiple Lua states in a portable way.
>>    
>
> i think the LuaArgs object could have a reference to the LuaInterpreter
> object; if you need it, just call an accessor method.
>  
Exactly.
> also, the luaReturn in particular could be a macro (so it can do a full
> return), but should get a reference either to the LuaInterpreter object or
> the LuaArgs (and therefore to the LuaInterpreter itself).
>  
There might be other ways that would avoid macros. E.g. having the
return value in the function args:

    void func(const LuaArgs& args, LuaReturn& ret)
    {
        ...
    }

Both could have references to the LuaInterpreter object. You could even
overload for the cases where you know there are no return values ever,
allowing you to write

    void func(const LuaArgs& args)
    {
        ...
    }

for a function that returns nothing to the lua interpreter.

Thanks for your input Javier. Cheers,
Oliver






Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Oliver Schoenborn-2
In reply to this post by Chris Marrin
Chris Marrin wrote:

> 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:
>
> 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);
>     }
>
> [...snip for brevity...]
> 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...
>
Worth looking into for sure. I'm not super keen on using class
inheritance (could get messy when MyClass inherits from other stuff and
they too use Function::Object, perhaps you could comment on that), but
lots of good ideas there, and maybe some code to re-use?

Oliver



Reply | Threaded
Open this post in threaded view
|

Re: request for interest/participants: another lua C++ binding

Chris Marrin
Oliver Schoenborn wrote:

> ...
>> [...snip for brevity...]
>> 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...
>>
> Worth looking into for sure. I'm not super keen on using class
> inheritance (could get messy when MyClass inherits from other stuff and
> they too use Function::Object, perhaps you could comment on that), but
> lots of good ideas there, and maybe some code to re-use?

The really nice thing about the system is that you work very naturally
in both C++ and Lua. It certainly has an issue with multiple
inheritance. You can only register functions from the first superclass.
But this can be overcome by using an adaptor to functions in subsequent
superclasses in the first one.

YMMV, but we have built lots of Objects with this system and it works
really well. But please use as much or as little as is useful to you...

--
chris marrin              ,""$, "As a general rule,don't solve puzzles
[hidden email]        b`    $  that open portals to Hell" ,,.
         ,.`           ,b`    ,`                            , 1$'
      ,|`             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`