passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

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

passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Gmail-3
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Tom McCubbin-2
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Gmail-3
Thanks very much for your quick replay, the information you provided is really very helpful.
But what i need if the object is created in the c++ side how to pass its pointer or reference or even copy it to the lua function.
Thanks

On Sun, Jan 25, 2009 at 5:01 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Gmail-3
Also i want to make use the stack mechanism of lua because i need to make a dynamic function call so i designed it using the push mechanism,
 
Again what i need:
 
C++:
Class1 * class  = ClassFactory::getInstance()->createInstance("Class1");

lua_getfield(m_LuaState,-1,

this->m_funcname.c_str());

if(lua_isfunction(m_LuaState,-1))

{

     push(class);
     pcall....;

}

in Lua:

function Func(obj)
   obj:move()
end
Thanks
 
On Sun, Jan 25, 2009 at 10:39 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Thanks very much for your quick replay, the information you provided is really very helpful.
But what i need if the object is created in the c++ side how to pass its pointer or reference or even copy it to the lua function.
Thanks

On Sun, Jan 25, 2009 at 5:01 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem



--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Tom McCubbin-2
In reply to this post by Gmail-3
Kariem,

I was worried you'd miss it in all the noise.  In fact in that example the object is created in c++ and then passed to lua.  You don't notice the actual object creation because the (c++) object is passed to the handle_quote( ) method in c++ which in turn invokes the lua callback (aka function):

    void
    handle_quote( const quote &q )  // this q is a c++ quote object and in the body here i will call a lua func passing it directly
    {
...

      func( &q );  // func is a lua function and I am passing it a pointer to the quote q that was passed to me...
...
    }
   
The point being that lua functions are first class objects and you can use the luabind::object class to encapsulate it and then invoke it w/ whatever c++ objects you may like.  AS long as caller and callee agree on that arg list ;)

i hope that helps,

-tom


On Sun, Jan 25, 2009 at 3:39 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Thanks very much for your quick replay, the information you provided is really very helpful.
But what i need if the object is created in the c++ side how to pass its pointer or reference or even copy it to the lua function.
Thanks

On Sun, Jan 25, 2009 at 5:01 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Tom McCubbin-2
In reply to this post by Gmail-3
Kariem,

I was worried you'd miss it in all the noise.  In fact in that example the object is created in c++ and then passed to lua.  You don't notice the actual object creation because the (c++) object is passed to the handle_quote( ) method in c++ which in turn invokes the lua callback (aka function):

    void
    handle_quote( const quote &q )  // this q is a c++ quote object and in the body here i will call a lua func passing it directly
    {
...

      func( &q );  // func is a lua function and I am passing it a pointer to the quote q that was passed to me...
...
    }
   
The point being that lua functions are first class objects and you can use the luabind::object class to encapsulate it and then invoke it w/ whatever c++ objects you may like.  AS long as caller and callee agree on that arg list ;)

i hope that helps,

-tom


On Sun, Jan 25, 2009 at 4:05 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Also i want to make use the stack mechanism of lua because i need to make a dynamic function call so i designed it using the push mechanism,
 
Again what i need:
 
C++:
Class1 * class  = ClassFactory::getInstance()->createInstance("Class1");

lua_getfield(m_LuaState,-1,

this->m_funcname.c_str());

if(lua_isfunction(m_LuaState,-1))

{

     push(class);
     pcall....;

}

in Lua:

function Func(obj)
   obj:move()
end
Thanks
 
On Sun, Jan 25, 2009 at 10:39 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Thanks very much for your quick replay, the information you provided is really very helpful.
But what i need if the object is created in the c++ side how to pass its pointer or reference or even copy it to the lua function.
Thanks

On Sun, Jan 25, 2009 at 5:01 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem



--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Tom McCubbin-2
You may also want to look at:

http://www.nuclex.org/articles/quick-introduction-to-luabind

It has some really clean simple examples of calling lua functions from c++.  The thing to note is while they pass ints you can pass pointers to luabind defined objects as well.

More important, all functions in lua are called by pushing and popping the stack.  Luabind does the lifting for you.  The simplest thing is just to hack a quick Makefile and driver c++ app and prove the point to yourself. 

Most importantly, luabind can do what you need.  (Thanks to the Boost Pros ;) )

-tom

On Sun, Jan 25, 2009 at 4:22 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

I was worried you'd miss it in all the noise.  In fact in that example the object is created in c++ and then passed to lua.  You don't notice the actual object creation because the (c++) object is passed to the handle_quote( ) method in c++ which in turn invokes the lua callback (aka function):

    void

    handle_quote( const quote &q )  // this q is a c++ quote object and in the body here i will call a lua func passing it directly
    {
...

      func( &q );  // func is a lua function and I am passing it a pointer to the quote q that was passed to me...
...
    }
   
The point being that lua functions are first class objects and you can use the luabind::object class to encapsulate it and then invoke it w/ whatever c++ objects you may like.  AS long as caller and callee agree on that arg list ;)

i hope that helps,

-tom


On Sun, Jan 25, 2009 at 4:05 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Also i want to make use the stack mechanism of lua because i need to make a dynamic function call so i designed it using the push mechanism,
 
Again what i need:
 
C++:
Class1 * class  = ClassFactory::getInstance()->createInstance("Class1");

lua_getfield(m_LuaState,-1,

this->m_funcname.c_str());

if(lua_isfunction(m_LuaState,-1))

{

     push(class);
     pcall....;

}

in Lua:

function Func(obj)
   obj:move()
end
Thanks
 
On Sun, Jan 25, 2009 at 10:39 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Thanks very much for your quick replay, the information you provided is really very helpful.
But what i need if the object is created in the c++ side how to pass its pointer or reference or even copy it to the lua function.
Thanks

On Sun, Jan 25, 2009 at 5:01 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem



--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Gmail-3

Thanks very much Tom, you are the man!!!
I was able to call the cunction the way i want.
Thanks again man.

 
On Sun, Jan 25, 2009 at 11:29 PM, Tom McCubbin <[hidden email]> wrote:
You may also want to look at:

http://www.nuclex.org/articles/quick-introduction-to-luabind

It has some really clean simple examples of calling lua functions from c++.  The thing to note is while they pass ints you can pass pointers to luabind defined objects as well.

More important, all functions in lua are called by pushing and popping the stack.  Luabind does the lifting for you.  The simplest thing is just to hack a quick Makefile and driver c++ app and prove the point to yourself. 

Most importantly, luabind can do what you need.  (Thanks to the Boost Pros ;) )

-tom


On Sun, Jan 25, 2009 at 4:22 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

I was worried you'd miss it in all the noise.  In fact in that example the object is created in c++ and then passed to lua.  You don't notice the actual object creation because the (c++) object is passed to the handle_quote( ) method in c++ which in turn invokes the lua callback (aka function):

    void

    handle_quote( const quote &q )  // this q is a c++ quote object and in the body here i will call a lua func passing it directly
    {
...

      func( &q );  // func is a lua function and I am passing it a pointer to the quote q that was passed to me...
...
    }
   
The point being that lua functions are first class objects and you can use the luabind::object class to encapsulate it and then invoke it w/ whatever c++ objects you may like.  AS long as caller and callee agree on that arg list ;)

i hope that helps,

-tom


On Sun, Jan 25, 2009 at 4:05 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Also i want to make use the stack mechanism of lua because i need to make a dynamic function call so i designed it using the push mechanism,
 
Again what i need:
 
C++:
Class1 * class  = ClassFactory::getInstance()->createInstance("Class1");

lua_getfield(m_LuaState,-1,

this->m_funcname.c_str());

if(lua_isfunction(m_LuaState,-1))

{

     push(class);
     pcall....;

}

in Lua:

function Func(obj)
   obj:move()
end
Thanks
 
On Sun, Jan 25, 2009 at 10:39 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Thanks very much for your quick replay, the information you provided is really very helpful.
But what i need if the object is created in the c++ side how to pass its pointer or reference or even copy it to the lua function.
Thanks

On Sun, Jan 25, 2009 at 5:01 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem



--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: passing an pointer of an object instance created in c++ for a class bound using luabind (not using call_function i need to use plain lua_pcall)

Tom McCubbin-2
All credit to Daniel Wallin!  After extending into most script languages by hand, swig, et. al. Daniel has put together a fantastic tool.  And I'm sure he'd lay some credit to boost.python as well.  I'm just happy to kick in to support the cause once in a blue moon :)

Happy to help...

On Sun, Jan 25, 2009 at 4:37 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:

Thanks very much Tom, you are the man!!!
I was able to call the cunction the way i want.
Thanks again man.

 
On Sun, Jan 25, 2009 at 11:29 PM, Tom McCubbin <[hidden email]> wrote:
You may also want to look at:

http://www.nuclex.org/articles/quick-introduction-to-luabind

It has some really clean simple examples of calling lua functions from c++.  The thing to note is while they pass ints you can pass pointers to luabind defined objects as well.

More important, all functions in lua are called by pushing and popping the stack.  Luabind does the lifting for you.  The simplest thing is just to hack a quick Makefile and driver c++ app and prove the point to yourself. 

Most importantly, luabind can do what you need.  (Thanks to the Boost Pros ;) )

-tom


On Sun, Jan 25, 2009 at 4:22 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

I was worried you'd miss it in all the noise.  In fact in that example the object is created in c++ and then passed to lua.  You don't notice the actual object creation because the (c++) object is passed to the handle_quote( ) method in c++ which in turn invokes the lua callback (aka function):

    void

    handle_quote( const quote &q )  // this q is a c++ quote object and in the body here i will call a lua func passing it directly
    {
...

      func( &q );  // func is a lua function and I am passing it a pointer to the quote q that was passed to me...
...
    }
   
The point being that lua functions are first class objects and you can use the luabind::object class to encapsulate it and then invoke it w/ whatever c++ objects you may like.  AS long as caller and callee agree on that arg list ;)

i hope that helps,

-tom


On Sun, Jan 25, 2009 at 4:05 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Also i want to make use the stack mechanism of lua because i need to make a dynamic function call so i designed it using the push mechanism,
 
Again what i need:
 
C++:
Class1 * class  = ClassFactory::getInstance()->createInstance("Class1");

lua_getfield(m_LuaState,-1,

this->m_funcname.c_str());

if(lua_isfunction(m_LuaState,-1))

{

     push(class);
     pcall....;

}

in Lua:

function Func(obj)
   obj:move()
end
Thanks
 
On Sun, Jan 25, 2009 at 10:39 PM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Thanks very much for your quick replay, the information you provided is really very helpful.
But what i need if the object is created in the c++ side how to pass its pointer or reference or even copy it to the lua function.
Thanks

On Sun, Jan 25, 2009 at 5:01 PM, Tom McCubbin <[hidden email]> wrote:
Kariem,

Assuming you have bound the class, and the module is loaded and bootstrapped in the lua_State vm, this is perfectly legal and works great.  I do it all the time.

The thing you need to think about is how you get a hold of the function you want to call.  Here is a small sample from a project that extends some trading infrastructure in  c++ into lua for fast trading model testing...

  // this is just normal luabind stuff registering the market (c++) class in lua
  // and is how from lua people request a market data subscription ( an async stream of realtime equity quotes )
  luabind::scope
  register_market()
  {

    using namespace trd;
    return lb::class_<trd::market>("market")
      .def( "get_market_data_subscription", & market::get_market_data_subscription )
      .property( "current_time", & market::get_current_time )
      ;
  }

  ...
  // here we register an extra class written just to handle callbacks into lua for market_data_subscriptions
  // its definition follows
  lb::class_<market_data_subscription_watch>( "market_data_subscription_watch" )
    .def( lb::constructor<trd::market_data_subscription &,lb::object>() );

  // this class adapts a sigc++ callback with quote information to reach into lua land
  // to a user defined callback
  class market_data_subscription_watch : public sigc::trackable
  {
  public:

    // it takes the c++ mkt data subsr. and a lua table where the key 'quote' points to a lua function
    // that takes one argument, quote object (also registered w/ luabind but not shown here)
    market_data_subscription_watch( market_data_subscription &sub, object table ) : m_lua_state( table.interpreter() )
    {

      // you need to make sure the table passed from lua isnt garbage collected and we can't keep refs for it
      // so i place the table in our registry over the next several lines
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      table.push( m_lua_state );  // push the table for our callbacks so lua won't gc the mfsob!
      lua_rawset( m_lua_state, -3 ); // now set the value in our fing table

      // this is just sigc++ stuff to have our c++ handle_quote( ) called when a quote arrives
      sub.signal_quote().connect( sigc::mem_fun( this, & market_data_subscription_watch::handle_quote ) );
    }
    ~market_data_subscription_watch()
    {
      // clean up of the mds requires releasing refs to the table so it can be gc'd as needed
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_pushnil( m_lua_state ); // nil out the entry
      lua_rawset( m_lua_state, -3 );
    }

    void
    handle_quote( const quote &q )
    {
      // the next several lines retrieve our lua table
      lua_pushlightuserdata( m_lua_state,  m_lua_state ); // the ptr to our lua state will be the index of our ref table
      lua_rawget( m_lua_state, LUA_REGISTRYINDEX ); // now the registry table for our module is on top of stack

      lua_pushlightuserdata( m_lua_state, this );  // we will put our stuff indexed by the ptr to this :)
      lua_rawget( m_lua_state, -2 );

      // now the table passed into the constructor is retrieved
      object m_table( from_stack( m_lua_state, -1 ) );

      // sanity check to make sure it actually was a table
      if ( type( m_table ) == LUA_TTABLE )
      {
        // here i retireve the lua function from the table
        object func = m_table["quote"];
 
        // sanity check...make sure it is a function
        if ( type(func) == LUA_TFUNCTION )
        {
          finally call the lua function passing the quote
          try {
            func( &q );
          } catch ( const luabind::error &e ) {
            luabind::object err( luabind::from_stack( e.state(), -1 ) );
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), luabind::object_cast<const char *>( err ) );
         } catch ( const std::runtime_error &e ) {
           TDEBUG( ACE_TEXT( "market_data_subscription_watch::handle_quote failed: %s\n"), e.what() );
         } catch ( ... ) { }
       }
      }
    }

  protected:
    lua_State *    m_lua_state;

  };


From lua you have something like this:

-- some lua callback function that gets quotes
function my_quote_callback( quote )
  print (string.format( "WE HAVE QUOTE: %4.2f - %4.2f", quote.bid, quote.ask ) )
end
 
...
-- somewhere else in the code
-- assuming you have model already and is a luabind model object
mds = model:get_market_data_subscription( "JDSU" );
watch = market_data_subscription_watch( mds, { quote = my_quote_callback } );

Now whenever a quote comes in, my_quote_callback will be called and as you see in that function, it can happily access the quote objects properties, methods, etc...

Hope this helps and wasn't too much...I was too lazy to write a stripped down version.  Feel free to post more ?'s if you need.

-tom

On Sun, Jan 25, 2009 at 8:31 AM, Kariem mohmed abdel fattah <[hidden email]> wrote:
Hi all,
I want to know if possible to call a lua function using lua_pcall and lua's stack but passing to that function a pointer to an object of luabind bound class, and be able to call the bound methods on that object from lua function.


c++:
push(something);
lua_pcall(L,1,0,0);

lua:
function testFunc(pointer)
 pointer:someBoundMethod()
end

Thanks

--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem



--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user




--
Kariem

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user



------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user