Re: [luabind] passing an pointer of an object instance created in c++ for a class bound using luabi
Brought to you by:
arvidn,
daniel_wallin
From: Tom M. <tom...@gm...> - 2009-01-25 15:01:12
|
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 < kar...@gm...> 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 > lua...@li... > https://lists.sourceforge.net/lists/listinfo/luabind-user > > |