lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Thanks Jeffrey for your code snippet. I will give it a try! But i have
expected this would be a feature of LUA to call functions/mehtods in an
other LUA context. I'm a bit surprised...is that really the only way?

>> Date: Thu, 01 Sep 2005 08:18:21 +0200
>> From: Mario <www.derfordfahrer@gmx.de>
>> Subject: calling fcuntion from other lua context
>> To: lua@bazar2.conectiva.com.br
>> Message-ID: <43169D2D.7000806@gmx.de>
>> Content-Type: text/plain; charset=us-ascii
>>
>> Hi all!
>>
>> I have some c++ objects, all with their own lua context. How is it
>> possible to call a lua function from one lua context to an another one?
>> For example:
>>
>>
>> script 1:
>> function CObject:OnLogic( )
>>
>>  local a = wmanager:getEntityByName( "NewObject" );
>>  a:some_function( )
>>
>> end
>>
>>
>> script 2:
>> function CObject:OnLogic( )
>> -- do nothing
>> end
>>
>> function CObject:some_function( )
>> io.write("Hi there!\n")
>> end
>>
>> I'm getting the error message "attempt to call method `some_function' (a
>> nil value)"?
>>
>> Thank you in advance!
>> Greetings Mario
> 
> 
> 
> Today I was just "solving" the same problem myself.  It is really
> complicated and not easy to do imho.  Here is a snippet of code that I
> made which does it although it has a limitation in that you can only
> pass and return arguments that are bool, string, number or nil...
> although the code could be exanded to do more.  Some of the code
> contains stuff my personal library I called bindlua, but I think it
> might at least give you something you can work with.
> 
> int lua_state_to_state_func_call(lua_State* L)
> {
> lua_State* LO = static_cast<lua_State*>(lua_touserdata(L,
> upvalueindex<1>::VAL));
> const char* func = lua_tostring(L, upvalueindex<2>::VAL);
> 
> const int LO_origTop = lua_gettop(LO);
> lua_pushstring(LO, func);
> lua_gettable(LO, LUA_GLOBALSINDEX);
> // the func to call is now on top of LO
> // Now put the args on LO, they r current in L
> 
> bool error = false;
> const int args = lua_gettop(L);
> for(int i = 1; i <= args; ++i)
> {
>  if(lua_type(L, i) == LUA_TSTRING)
>  {
>   const char* s = lua_tostring(L, i);
>   lua_pushstring(LO, s);
>  }
>  else if(lua_type(L, i) == LUA_TNUMBER)
>  {
>   lua_Number n = lua_tonumber(L, i);
>   lua_pushnumber(LO, n);
>  }
>  else
>  {
>   std::ostringstream oss;
>   oss << "state to state func call does not support arg (" << i << ")
> type: " << lua_typename(L, lua_type(L, i));
>   lua_warning(L, oss.str());
>   error = true;
>  }
> }
> 
> if(error)
> {
>  lua_settop(LO, LO_origTop);
>  return 0;
> }
> 
> try
> {
>  lua_pcall(LO, args, LUA_MULTRET, 0);
>  const int results = lua_gettop(LO) - LO_origTop;
>  for(int i = LO_origTop + 1; i <= lua_gettop(LO); ++i)
>  {
>   if(lua_type(LO, i) == LUA_TSTRING)
>   {
>    const char* s = lua_tostring(LO, i);
>    lua_pushstring(L, s);
>   }
>   else if(lua_type(LO, i) == LUA_TNUMBER)
>   {
>    lua_Number n = lua_tonumber(LO, i);
>    lua_pushnumber(L, n);
>   }
>   else
>   {
>    std::ostringstream oss;
>    oss << "state to state func call does not support ret val type: " <<
> lua_typename(LO, lua_type(LO, i));
>    lua_warning(LO, oss.str());
>    return 0;
>   }
>  }
> 
>  lua_settop(LO, LO_origTop);
>  return results;
> }
> catch(bindlua_exception& e)
> {
>  lua_warning(L, e.what());
> }
> }
> 
> // Here pScr is an object which olds the state of the "other object"
> // L is the state that is calling a function in the other ob
> // ie: x = ob.SomeFunc(1,2,3);
> // ob is a userdata holding pScr, and through some code of my bindlua
> library you eventually get to this
> // unhanded_get code, which makes a dispatch to the
> state_to_state_func_call above
> template<>
> int unhandled_get(const Interface::ScriptPtr& pScr, const std::string&
> key, lua_State* L)
> {
> bindlua::lua_state LB = pScr->GetState();
> lua_getglobal(LB, key);
> if(lua_isnil(LB, -1))
> {
>  lua_pop(LB, 1);
>  return 0;
> }
> if(lua_type(LB, -1) == LUA_TFUNCTION)
> {
>  lua_pushlightuserdata(L, LB.get());
>  lua_pushstring(L, key);
>  lua_pushcclosure(L, lua_state_to_state_func_call, 2);
>  return 1;
> }
> if(lua_type(LB, -1) == LUA_TSTRING)
> {
>  std::string s = lua_tostring(LB, -1);
>  lua_pushstring(L, s);
>  return 1;
> }
> std::ostringstream oss;
> oss << "unsupported type in script to script transfer, type: " <<
> lua_typename(LB.get(), lua_type(LB.get(), -1));
> lua_warning(L, oss.str());
> return 0;
> }
> 
> 
>