[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: calling fcuntion from other lua context
- From: "Jeffrey Williams" <jwilliams@...>
- Date: Thu, 1 Sep 2005 18:33:41 -0400
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;
}