Get the lua command when a c function is called - c++

Supposed I register many different function names in Lua to the same function in C. Now, everytime my C function is called, is there a way to determine which function name was invoked?
for example:
int runCommand(lua_State *lua)
{
const char *name = // getFunctionName(lua) ? how would I do this part
for(int i = 0; i < functions.size; i++)
if(functions[i].name == name)
functions[i].Call()
}
int main()
{
...
lua_register(lua, "delay", runCommand);
lua_register(lua, "execute", runCommand);
lua_register(lua, "loadPlugin", runCommand);
lua_register(lua, "loadModule", runCommand);
lua_register(lua, "delay", runCommand);
}
So, how do I get the name of what ever function called it?

Another way to attack your question is by using upvalues. Basically, you register the C functions with the function below instead of lua_register:
void my_lua_register(lua_State *L, const char *name, lua_CFunction f)
{
lua_pushstring(L, name);
lua_pushcclosure(L, f, 1);
lua_setglobal(L, name);
}
Then, getFunctionName is straight forward
const char* getFunctionName(lua_State* L)
{
return lua_tostring(L, lua_upvalueindex(1));
}
That said, what you trying to do seems fishy - what are you trying to achieve? The runCommand function posted in the question looks like a horribly inefficient way to do something that Lua does for you anyway.

You can use lua_getinfo : http://pgl.yoyo.org/luai/i/lua_getinfo
This might work:
const char* lua_getcurrentfunction(lua_State* L) {
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "f", &ar);
return ar.name;
}
There is one caveat:
name: a reasonable name for the given function. Because functions in Lua are first-class values, they do not have a fixed name: some functions may be the value of multiple global variables, while others may be stored only in a table field. The lua_getinfo function checks how the function was called to find a suitable name. If it cannot find a name, then name is set to NULL.

An alternative solution would be to register a metatable for the Lua environment table that implements the __index metamethod for dispatching these functions calls.

Unfortunately, that's not possible - among other things, because functions in Lua don't actually have to have a name at all. (Consider: (loadstring("a=1"))() is executing a nameless function returned from loadstring.)

If you're willing to slurp up all unknown function executions, you may be able to play games with setmetatable and currying:
-- This function would not be in lua in your example,
-- you'd be doing lua_register( lua, "runCommandNamed", runCommandNamed )
-- and writing a runCommandNamed in C.
function runCommandNamed( cmd, ... )
print( "running command", cmd, "with arguments", ... )
end
-- The rest would be somewhere in lua-land:
local utilMetaTable = {
__index = function ( t, key )
return function( ... ) -- mmm, curry
runCommandNamed( key, ... )
end
end
}
_util = {}
setmetatable( _util, utilMetaTable )
-- prints "running command CommandOne with arguments arg1 arg2 arg3"
_util.CommandOne( "arg1", "arg2", "arg3" )
-- prints "running command CommandTwo with arguments argA argB"
_util.CommandTwo( "argA", "argB" )
In this example, I've only slurped up unknown executions under _util rather than in the global table.

Related

Lua: fails to get field after loading a second string;

Good afternoon,
I am working on a LUA/C++ application, from which i need lua to be able to call other lua code recursively, e.g: C++ calls lua function, lua function calls another lua function from another string that is loaded using a registered C function that runs at the start of the first lua function;
here are the steps i am following:
lua_State* state = luaL_newstate();
luaL_openlibs(state);
lua_register(state, "secondLua", secondLua);
lua_getfield( _luaState, LUA_GLOBALSINDEX, "init" );
lua_pcall( _luaState, 0, 0, 0 );
int secondLua(lua_State* state){
char* myString[128] = "function init2()\n io.write(\"hello\")\n end";
luaL_loadstring(pLuaState, myString);
lua_getfield(pLuaState,LUA_GLOBALSINDEX, "init2"); // function init2 declared on myString
lua_pcall(pLuaState, 0, LUA_MULTRET, 0);
//getting "attempt to call a nil value" here
return 0;
}
Any help is appreciated, and second, i would like to know if there is a way i can name the second function "init" as well as the first one;
PS: I am using C++14 and lua 5.1 on LUAJIT, and i cant use lua's dofile;
lua_loadstring() compiles supplied source and puts Lua chunk on stack. It won't execute it though, so init2() still not defined when you expect that.
Replace lua_loadstring() with luaL_dostring() to actually run that chunk and define new lua functions. Or call lua_pcall() right after lua_loadstring(). Actually, luaL_dostring() does exactly that - lua_loadstring() followed by lua_pcall().

how do I extend Lua with a static c++ library?

I have a Visual Studio 2008 C++03 application that uses Lua 5.2.1. I would like to extend Lua with a module called "foo", but when I call require("foo") in my Lua script, I get the error:
foo_test.lua:1: module 'foo' not found:
no field package.preload['process']
no file '!\lua\process.lua'
no file '!\lua\process\init.lua'
no file '!\process.lua'
no file '!\process\
My Lua script:
foo.bar()
My lua_foo.h file:
#include <lua.h>
extern "C" int luaopen_foo( lua_State* L );
My lua_foo.cpp file:
#include "lua_foo.h"
#include <lua.hpp>
static int l_bar( lua_State *L )
{
puts( "in bar()" );
return 1;
}
int luaopen_foo( lua_State *L )
{
static const luaL_Reg foo[] = {
{ "bar", l_bar },
{ NULL, NULL }
};
luaL_newlib( L, foo );
return 1;
}
These are compiled in to a static library "lua_foo.lib" which is statically linked to my main Lua executable.
Can anybody help me understand where I'm going wrong? thanks. I would prefer to avoid c++ wrappers (for now) and I do not want to package this library as a separate DLL from the main Lua engine.
EDIT
The issue was in the lua engine code. I added the luaL_requiref per #NicolBolas 's suggestion.
lua_State* L = luaL_newstate();
if( NULL != L )
{
luaL_openlibs( L );
luaL_requiref( token.get(), "foo", luaopen_foo, 1 );
luaL_dofile( L, "foo_test.lua" );
lua_close( L );
}
It's important to understand how the require machinery works and therefore why your code doesn't.
require is designed to look for Lua scripts in the file system and DLLs. Static libraries are not DLLs; indeed, as far as C/C++ is concerned, once you've finished linking, static libraries are no different than compiling those .c/.cpp files into your application directly.
When require finds a DLL with the appropriate name, it loads it and attempts to find a function named luaopen_<modname>, where <modname> is the name of the module. When it does, it will execute this function and store the value it returns in an internal database of loaded modules.
Calling require for a module will return whatever this function returned; if the module has already been loaded, then the return value is pulled from the database and returned directly.
Simply calling luaopen_foo will not do any of this. Indeed, simply calling this function is a bad idea; it is a Lua function and needs to be called as a Lua function (ie: you need to push it onto the Lua stack with lua_pushcfunction and call it with lua_call and so forth).
If you want to create a local module (one not in a Lua script or DLL, but exposed from your code), then you need to use the Lua facilities to do that. Specifically, use luaL_requiref:
luaL_requiref(L, "foo", luaopen_foo, 0);
Call this instead of calling luaopen_foo directly. This will automatically register the return value from luaopen_foo with require's internal database of loaded modules. Thus, subsequent calls to require "foo" will return this table.
One more thing: do is a keyword in Lua; you should not use keywords for Lua table key names. You can, but you always have to quote them (ie: your script must do foo["do"](...) to call it).
luaopen_foo creates a table with one function in it, but it doesn't expose it to Lua in any way. You need to assign it to something your scripts can access if you want to access it. You can do this with the package mechanism, or just assign it to a global (which is what Lua's built-in libraries do).
You have a field named do, which is problematic if you want to use foo.do syntax, because do is a keyword.
The return value of a Lua function tells Lua how many values you left on the stack. Your l_do function lies with its return value.
In the case of luaopen_foo, since you're calling it directly and ignoring it's return value, there's no need for it to return anything at all.
Change your code to this:
static int l_bar( lua_State *L )
{
puts("l_bar called.");
return 0;
}
void luaopen_foo( lua_State *L )
{
static const struct luaL_Reg foo[] = {
{ "bar", l_bar },
{ NULL, NULL }
};
luaL_newlib( L, foo ); // create table containing `bar`
lua_setglobal(L, "foo"); // assign that table to global `foo`
}
And change your script to this:
foo.bar()

luabind: Can't call basic lua functions like print, tostring

A very basic question i guess:
The C++ code, calling lua looks like this:
lua_State* m_L;
m_L = lua_open();
luabind::open(m_L);
luaL_dofile(m_L, "test.lua");
try {
luabind::call_function<void>(m_L, "main");
} catch (luabind::error& e) {
std::string error = lua_tostring(e.state(), -1);
std::cout << error << std::endl;
}
lua_close(m_L);
now test.lua has the following contents:
function main()
print "1"
end
Upon execution I receive the error:
test.lua:2: attempt to call global 'print' (a nil value)
What is the problem? It has something to do with environments? I thought functions like print are defined in the global environment. Why is it not found then?
Thank you very much.
As you figured it out, you have to call luaopen_base to get print and other base functions. Then you need to call luaopen_string, luaopen_math, to get the basic modules and functions in. Instead of writing it all out manually, can load all Lua base function at once with luaL_openlibs:
lua_State* m_L = luaL_newstate();
luaL_openlibs(m_L);

Redirecting/redefining print() for embedded Lua

I have embedded Lua in my C++ application. I want to redirect print statements (or maybe simply redefine the print function?), so that I can display the evaluated expression somewhere else.
What is the best way to do this: redirect or redefining the print() function?
Any snippets/pointers to snippets that show how to do this would be much appreciated.
You can redefine the print statement in C:
static int l_my_print(lua_State* L) {
int nargs = lua_gettop(L);
for (int i=1; i <= nargs; i++) {
if (lua_isstring(L, i)) {
/* Pop the next arg using lua_tostring(L, i) and do your print */
}
else {
/* Do something with non-strings if you like */
}
}
return 0;
}
Then register it in the global table:
static const struct luaL_Reg printlib [] = {
{"print", l_my_print},
{NULL, NULL} /* end of array */
};
extern int luaopen_luamylib(lua_State *L)
{
lua_getglobal(L, "_G");
// luaL_register(L, NULL, printlib); // for Lua versions < 5.2
luaL_setfuncs(L, printlib, 0); // for Lua versions 5.2 or greater
lua_pop(L, 1);
}
Since you are using C++ you'll need to include your file using 'extern "C"'
You can simply redefine print from a Lua script.
local oldprint = print
print = function(...)
oldprint("In ur print!");
oldprint(...);
end
See luaB_print in lbaselib.c. The comment there reads:
/* If you need, you can define your own `print' function, following this
model but changing `fputs' to put the strings at a proper place (a
console window or a log file, for instance). */
You can just edit that function or define a new one. This has the advantage of being simple and portable, but it won't handle io.write (which you may or may not care about).
Redirecting IO isn't going to be platform specific (such as SetStdHandle in Windows), but will take care of print and io.write without redefining either.
Write your own C or Lua function and redefine print.
You can just redefine the following macros:
lua_writestring
lua_writeline
lua_writestringerror
to whatever you like.
I'm not sure about the lua version where this was introduced - but it works in 5.3 for me.
Check your lauxlib.h or luaconf.h.

Looking for the most elegant code dispatcher

I think the problem is pretty common. You have some input string, and have to call a function depending on the content of the string. Something like a switch() for strings.
Think of command line options.
Currently I am using:
using std::string;
void Myclass::dispatch(string cmd, string args) {
if (cmd == "foo")
cmd_foo(args);
else if (cmd == "bar")
cmd_bar(args);
else if ...
...
else
cmd_default(args);
}
void Myclass::cmd_foo(string args) {
...
}
void Myclass::cmd_bar(string args) {
...
}
and in the header
class Myclass {
void cmd_bar(string args);
void cmd_foo(string args);
}
So every foo and bar I have to repeat four (4!) times. I know I can feed the function pointers and strings to an static array before and do the dispatching in a loop, saving some if...else lines. But is there some macro trickery (or preprocessor abuse, depending on the POV), which makes is possible to somehow define the function and at the same time have it update the array automagically?
So I would have to write it only twice, or possibly once if used inline?
I am looking for a solution in C or C++.
It sounds like you're looking for the Command pattern
Something like this:
Create a map like this
std::map<std::string, Command*> myMap;
then just use your key to execute the command like this....
std::map<std::string, Command*>::iterator it = myMap.find(str);
if( it != myMap.end() ) {
it->second->execute()
}
To register your commands you just do this
myMap["foo"] = new CommandFoo("someArgument");
myMap["bar"] = new CommandBar("anotherArgument");
The basic solution, per my link in the question comment, is to map a string to a function call of some sort.
To actually register the string -> function pointer/functor pair:
Firstly, have a singleton (shock! horror!) dispatcher object.
Let's call it TheDispatcher - it's a wrapper for a map<string,Func>, where
Func is your function pointer or functor type.
Then, have a register class:
struct Register {
Register( comst string & s, Func f ) {
TheDispatcher.Add( s, f );
}
};
Now in your individual compilation units you create
static objects (shock! horror!):
Register r1_( "hello", DoSayHello );
These objects will be created (assuming the code is not in a static library) and will automatically register with TheDispatcher.
And at run-time, you look up strings in TheDispatcher and execute the associated function/functor.
as alternative to the Command pattern you can build an hashtable of string -> function pointers:
typedef void (*cmd)(string);
The ugly macro solution, which you kind-of asked for. Note that it doesn't automatically register, but it does keep some things synchronized, and also will cause compile errors if you only add to mappings, and not the function in the source file.
Mappings.h:
// Note: no fileguard
// The first is the text string of the command,
// the second is the function to be called,
// the third is the description.
UGLY_SUCKER( "foo", cmd_foo, "Utilize foo." );
UGLY_SUCKER( "bar", cmd_bar, "Turn on bar." );
Parser.h:
class Myclass {
...
protected:
// The command functions
#define UGLY_SUCKER( a, b, c ) void b( args )
#include Mappings.h
#undef UGLY_SUCKER
};
Parser.cpp:
void Myclass::dispatch(string cmd, string args) {
if (cmd == "")
// handle empty case
#define UGLY_SUCKER( a, b, c ) else if (cmd == a) b( args )
#include Mappings.h
#undef UGLY_SUCKER
else
cmd_default(args);
}
void Myclass::printOptions() {
#define UGLY_SUCKER( a, b, c ) std::cout << a << \t << c << std::endl
#include Mappings.h
#undef UGLY_SUCKER
}
void Myclass::cmd_foo(string args) {
...
}
You'll have to at least define the functions and add them to some registry. (If they are to be non-inline member functions of some class, you'll also have to declare them.) Other than some domain-specific language generating the actual code (like cjhuitt's macro hackery), I see no way around mentioning these functions two (or three) times.