Skip to main content
GameDev.net gamedev.net
🔒 Locked

getting the name of the called C function from lua

Started by irreversible Sep 25, 2008 at 6:17 PM 8 replies 1.6k views
Original Post
irreversible
irreversible
Example: lua code

IWantToKnowTheNameOfThisFuncInC1("a string")
IWantToKnowTheNameOfThisFuncInC2("another string")
C code

//load up a script and register two different functions to point to
//the same translator function, in this case luaTranslator():

lua_register(L, "IWantToKnowTheNameOfThisFuncInC1", luaTranslator);
lua_register(L, "IWantToKnowTheNameOfThisFuncInC2", luaTranslator);
lua_pcall(L, 0, LUA_MULTRET, 0);

static int luaTranslator(lua_State *lua)
{
//<- this is where I need to know the name of the calling function,
//which is either IWantToKnowTheNameOfThisFuncInC1 or
//IWantToKnowTheNameOfThisFuncInC2. How can I do that?
}
I need the translator function to do type checking before calling the actual C function and only have one single place around where I do that. This also means I don't want a bunch of forwarding functions. Another big plus of having a single translator function is encapsulation.
gekko
gekko
I don't really understand the issue. If forwarding functions are not your preference, how would you like to get the "name"? Are you looking for it as a string, a pointer to the Lua function?
-- gekko
irreversible
irreversible
Just a simple string - in this case, when luaTranslator() is called, I need to know whether it was called via "IWantToKnowTheNameOfThisFuncInC1()" or "IWantToKnowTheNameOfThisFuncInC2()".

Actually I'd also like lua_state to have a user argument field like the HWND class has a custom user data element (that you can set and get through SetWindowLong(GWL_USERATA) and GetWindowLong(GWL_USERATA)) or combo box items have a user data field. But I'm guessing that's a bit too much to ask. Knowing the name of the function used to call luaTranslator() is kinda imperative though.
ddn3
ddn3
This should be doable, you can defintely do a stack trace which will give you the correct function names of the callstack, so the information is available. Now sure how you would grab it from the C side vs Lua side. In the Lua side you can use the debug library, if its still enabled.

Look into how the debug stack walker is implemented, it will give u a good idea of how to extract the caller info.

Look in ldebug.c to see how the debug library extracts the stack information, it's in there somewhere.


Good Luck!

-ddn
niteice
niteice
Yep, that's how I did it. Look into the lua_Debug structure. I don't have access to my code right now but I'll post tomorrow.
irreversible
irreversible
Good idea! However, both lua_getlocal() and lua_getstack() are returning an empty lua_Debug structure (eg the structure is never modified) and the direct return value for lua_getlocal() for the first two arguments of the called function is "(*temporary)". I'm pretty sure I'm missing something here, though :). Although googling hasn't revealed any fancy semantics in addition to these...
Evil Steve
Evil Steve
Possibly relevant; from my engine code:
bool PScriptMgr::Register(EScriptFunction* pFunction){	// Register function with lua with pointer	lua_pushlightuserdata(m_pState, pFunction);	lua_pushcclosure(m_pState, StaticFunctionStub, 1);	lua_setglobal(m_pState, pFunction->GetName().c_str());	return true;}int PScriptMgr::StaticFunctionStub(lua_State* pState){	// Get the function	int nIdx = lua_upvalueindex(1);	EScriptFunction* pFunction = (EScriptFunction*)lua_topointer(pState, nIdx);	// Use pFunction here	return nRetvals;}

EScriptFunction in my engine is a class with a virtual Execute() function which I can use to call the C function.
You could modify the code to pass in the name of the function instead of the class pointer, and retrieve it in the same way in your C callback.
gekko
gekko
Quote:
Original post by irreversible
Actually I'd also like lua_state to have a user argument field like the HWND class has a custom user data element (that you can set and get through SetWindowLong(GWL_USERATA) and GetWindowLong(GWL_USERATA)) or combo box items have a user data field.


Are you running these scripts in separate threads? If so, you can create a table associating each lua_State* with some additional value. It makes it really convenient when you end up in a glue function to find data unique to the lua_State parameter.
-- gekko
irreversible
irreversible
Aight - I finally got around to this again. steve - that works splendidly - thanks for the solution! Using a look-up table was my second option, but it seems like such a retarded way for so many reasons.

However, I still can't get the debug information to display correctly. Here's what I'm trying:

int i = 1;const char* name = NULL;while ((name = lua_getlocal(lua, &dbg, i++)) != NULL) {  lout << name << endl;  lua_pop(lua, 1);  }


The output for a 5-argument function is verbatim:


(*temporary)
(*temporary)


I'm not sure if this is the right way to obtain debug information, but it certainly doesn't seem to be returning anything relevant. Furthermore, the returned debug structure is not modified in any way.
Evil Steve
Evil Steve
A little off topic here:

Quote:
Original post by irreversible
Aight - I finally got around to this again. steve - that works splendidly - thanks for the solution! Using a look-up table was my second option, but it seems like such a retarded way for so many reasons.
You obviously haven't seen what lua_register is then [smile]:
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.