Re: Lua-icxx-users post from dmangy@gmail.com requires approval

23 views
Skip to first unread message

oliver

unread,
Feb 10, 2012, 12:09:00 AM2/10/12
to lua-...@googlegroups.com, dma...@gmail.com
Hi Dom, great stuff in those messages. I created lua-icxx precisely because I use swig and don't want to mess around with stack indices etc. 

I have been thinking that it would be nice to wrap the  SWIG_Lua_NewPointerObj  for use in lua-icxx, but have not had time to find a solution that I really like. I think you are onto something, but I think there should be a way to write it more naturally. Using your example , 

void execCallback()
    {
       cb( new Foo );
    } 

I think this should be supportable via templates. The  SWIG_Lua_NewPointerObj   is defined in the SWIG-generated DLL, but I can't find a header where it is declared, probably missing a swtich in my swig.exe command. It would go something like this: 
  • extend the LuaFuncRef to have templated version that handles UDT separately
  • the template code is instantiated only on use, so if a user doesn't use SWIG, there should be no compile error
  • the header for Foo is included in the file that defines execCallback(), so Foo is known at the time the template is instantiated
  • user would include the swig-generated .h file so they get the SWIG_NewPointerObj would be known to the template code
Oliver

On Sun, Feb 5, 2012 at 5:09 PM, <lua-icxx-u...@lists.sourceforge.net> wrote:
As list administrator, your authorization is requested for the
following mailing list posting:

   List:    Lua-icx...@lists.sourceforge.net
   From:    dma...@gmail.com
   Subject: Re: lua_icxx + swig
   Reason:  Post by non-member to a members-only list

At your convenience, visit:

   https://lists.sourceforge.net/lists/admindb/lua-icxx-users

to approve or deny the request.


---------- Forwarded message ----------
From: Domenico Mangieri <dma...@gmail.com>
To: lua-icx...@lists.sourceforge.net
Cc: 
Date: Sun, 5 Feb 2012 22:08:53 +0000
Subject: Re: lua_icxx + swig
After looking carefully at the source code, I found that you make use of pushValToStack.

This can be used for a custom stack allocation to handle the swig call.

Here is what I've done :

I restored the original lua_icxx source code and added to LuaObjRef.h  the following code


struct LUA_ICXX_CPP_API
UserStackAllocation
{
     virtual void pushToStack(lua_State* L) const = 0;
};

void pushValToStack(lua_State* L, const UserStackAllocation& objRef)

    objRef.pushToStack(L);
}




In my code I derive from UserStackAllocation to handle the swig calls

class Swig : public
UserStackAllocation
{
    
Swig(Foo* f);

     void pushToStack(lua_State* L) const {
                    SWIG_Lua_NewPointerObj( L, .... );
          }
}



Now I can simply use the standard way of calling a function


    void execCallback()
    {
       cb( Swig( new Foo ) );
    }


This solution is cleaner
Let me know if you are interested in adding it to the project

Thanks

Dom

On Sun, Feb 5, 2012 at 7:12 PM, Domenico Mangieri <dma...@gmail.com> wrote:
I doesn't work as it is so I modified slightly lua_icxx code to accommodate this requirement.

This is just a quick solution..

with the changed code I can do this


    void execCallback()
    {
       LuaFuncCallParams call= cb.prepCall()   // this is now public

       SWIG_Lua_NewPointerObj( L, new Foo() .... )  // push wrapped object on the stack


       call.doCall(1);   // doCall gets extra number of params pushed on the stack
    }


        This works.  

        Maybe it can be implemented differently but I'm sure this could be a popular feature for lua_icxx as I think the combo swig + lua_icxx is a winner!

       
   Dom



On Sun, Feb 5, 2012 at 5:26 PM, Domenico Mangieri <dma...@gmail.com> wrote:
Hi ..  more on this..  

I found that I can use  SWIG_Lua_NewPointerObj  provided by swig generate file  to create the wrapping object


    void execCallback()
    {
       SWIG_Lua_NewPointerObj( L, new Foo() .... )


       cb();
    }

SWIG_Lua_NewPointerObj pushes the object into lua stack.

Now the question is, can I call cb with no args given the pointer is already in the stack  ?

I'll give it a try..

Dom




On Sun, Feb 5, 2012 at 3:34 PM, Domenico Mangieri <dma...@gmail.com> wrote:
Hi,

I'm playing around with lua_icxx. I find it very useful with its unique approach to lua calls within c++.

I'm currently using swig to wrap a large library and I'm using lua_icxx to provide callback supports from within c++ into lua.

Here is an example

c++

// Note : Foo is wrapped by swig

class Foo
{
  public:

    LuaFuncRef cb;

    void registerCallback(const char* cb)
    {
        cb = _lua.eval(cb);
    }
    .....

    void execCallback()
    {
       cb();
    }
};





lua :


function test()
    print("cool")
end

f = Foo()
f:registerCallback("test");




That's all good.

My problem now is to make use of swig wrap to pass c++ objects to lua callback;

Something like this

    void execCallback()
    {
       cb( new Foo );
    }

The callback works fine with basic types but not for UDT.

Any idead how that could be solved ?


Thank you for sharing this lib.

Dom






---------- Forwarded message ----------
From: lua-icxx-us...@lists.sourceforge.net
To: 
Cc: 
Date: 
Subject: confirm 91d72a70ea205946d1c0b45150a7f89a9ea77d01
If you reply to this message, keeping the Subject: header intact,
Mailman will discard the held message.  Do this if the message is
spam.  If you reply to this message and include an Approved: header
with the list password in it, the message will be approved for posting
to the list.  The Approved: header can also appear in the first line
of the body of the reply.

oliver

unread,
Feb 11, 2012, 11:24:07 PM2/11/12
to Domenico Mangieri, lua-...@googlegroups.com
On Sat, Feb 11, 2012 at 4:40 PM, Domenico Mangieri <dma...@gmail.com> wrote:
Hi Oliver,

Thanks for getting back.

You can generate the swig header file using the command   swig.exe -lua -external-runtime

The header file contains SWIG_NewPointerObj  along with other functions used by swig.


Thanks for the tip, looks like for Lua it is not generated by default, contrary to other languages like C#.
 
The template would be a nice solution but of difficult implementation as you need to know how to map the c++ class type to swig_type_info struct.

At the moment I'm doing that mapping manually in my code, as the number of classes that I use in the callbacks are few.

Here is an example  :

Note : all the  SWIGTYPE_p_* are pointers to swig_type_info defined the the generated swig cpp file


struct Swig : public UserAllocation
{
    Swig():_ptr(nullptr),_type(nullptr) {}
   
    template<typename T>
    Swig(T* node) { set(node); }

    void set(osg::Geode* node)       { init(node,SWIGTYPE_p_osg__Geode); }
    void set(osg::Group* node)       { init(node,SWIGTYPE_p_osg__Group); }
    void set(osg::NodeVisitor* node) { init(node,SWIGTYPE_p_osg__NodeVisitor); }

    virtual void pushToStuck(lua_State* L) const
    {
        SWIG_NewPointerObj(L,_ptr,_type,_own);
        }

protected:

    void init(void* ptr, swig_type_info* type, int own = 1)
    {
       
_ptr = ptr, _type = type,_own = own;
    }

    void* _ptr;
    swig_type_info* _type;
    int _own;
};


If you have an idea let me know I'm interested.

Thanks

Dom


 
Here are some other possibilities: 

struct Swig : public UserAllocation
{    
    
template<typename T>
    Swig(T* node): _ptr(node), _own(1), _type(SWIG_TypeQuery(typeid(node).name())) { }

    template<typename T>
    Swig(T* node, const char* name)
        : _ptr(node), _own(1), _type(SWIG_TypeQuery(name)) { }

    template<typename T>
    Swig(T* node, const swig_type_info* sti): _ptr(node), _own(1), _type(sti) { }
};

Clearly the first is worst performance but least reliance on developer, third is best performance but developer must pass in the correct swig_type_info. This is an issue: swig_type_info cannot be known at compile time, only runtime, eventhough the class T given to SWIG is known at compile time. Therefore we can't get away from having to either search for type info every time a T instance is given as argument to a LuaFunction call, or explicitly provide the swig_type_info. 

Perhaps a form of "registration" or "registry" would work: 

template<typename TT>
struct LuaSwigTyped {
    static swig_type_info* getSTI() { if (sti==NULL) initSTI(); return sti; }
    static swig_type_info* sti;
    static void initSTI() { sti = SWIG_TypeQuery(typeid(node).name()); }
}
template <typename TT>
pushValToStack(TT* obj) {
   assert(obj != NULL);
   swig_type_info* sti = LuaSwigTyped<TT>::getSTI(obj);
   // push...
}

or maybe even 

template<typename TT>
swig_type_info* getSTI(TT* obj) { 
    return SWIG_TypeQuery(typeid(obj).name()); 
}
template <typename TT>
pushValToStack(TT* obj) {
   assert(obj != NULL);
   static swig_type_info* sti = LuaSwig::getSTI(obj); // only done once per type!
   // push...
}

(swig_type_info is determined only once per type). Problem there is that typeid will return the most derived type if T is a polymorphic type, this would probably be undesirable. In that case a LuaInterpreter::register<TT>("className") might be a better approach: 

template<typename TT>
struct LuaSwigTyped {
    static swig_type_info* getSTI() { assert(STI); return sti; }
    static swig_type_info* sti;
    static void initSTI(const char*) { sti = SWIG_TypeQuery(name); }
}
LuaInterpreter::register<TT>(const char* name) {
    LuaSwigTyped<TT>::initSTI(name);
}
template <typename TT>
pushValToStack(TT* obj) {
   assert(obj != NULL);
   static swig_type_info* sti = LuaSwigTyped<TT>::getSTI();
   // push...
}

...
LuaInterpreter L;
L.register<Foo>("Foo");
LuaFunction f = L.eval("someFunc");
f(foo);// will use the swig_type_info associated during register<Foo>()

Do you want to try any of this? (Please use reply-all so your reply goes to the forum. )

Oliver


Reply all
Reply to author
Forward
0 new messages