Call Lua table function from C++ w/ self in function - c++

My goal is to simply call a table function from C++ that uses 'self' inside of the function to access fields and functions of that table. I keep getting the lovely 'attempt to call a nill value (local self)' on the line that has 'self.name'. Below is my Lua script.
Foo = { name = 'Foo' }
function Foo:OnUpdate()
print('In OnUpdate in Lua')
print(self.name)
end
Below is my C++ code (ignoring any error handling for now).
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "foo.lua");
lua_getglobal(L, "Foo");
lua_getfield(L, -1, "OnUpdate");
lua_pcall(L, 0, 0, 0);
When 'lua_pcall' is called, I see 'In OnUpdate in Lua' in the CLI, but never 'Foo'. If I check the error from 'lua_pcall' I get the error message mentioned above. Am I missing a certain Lua C API function prior to calling 'lua_pcall'? I am aware of the '.' vs. ':' in lua for utilizing 'self'. If I add a call in the Lua script like 'Foo:Update()', everything works perfectly. This has got me stumped.

You need to send the value of Foo as the first argument. So, do
lua_pushvalue(L, -2);
lua_pcall(L, 1, 0, 0);

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().

Lua Anonymous function storing in C++

I'm writing a Lua library in C++ that uses callbacks for certain functionalities. For testing I have 2 Lua functions, Register and Call. They are implemented in C++ like this:
int Lua_Register(lua_State* l){
int n = lua_gettop(l);
if(n==1){
if(lua_isfunction(l, -1)){
printf("Register\n")
lua_pushvalue(l, -1);
r = luaL_ref(l, LUA_REGISTRYINDEX);
}
}
return 1;
}
int Lua_Call(lua_State* l){
lua_rawseti(l, LUA_REGISTRYINDEX, r);
lua_call(l, 0, 0);
return 1;
}
and then in Lua:
Register(function()
Log("hi!")
end)
Call()
But all I see in the console is a lot of lines containing Register, followed by the message: C stack overflow. What I assume the problem is, is that I'm storing Register, rather than the anonymous function in the argument, which would create an infinite loop. How can I solve this?
Basically, You're trying to overwrite Lua registry with non-existant value instead of executing already set value.
What are You doing in short:
--calling Register()
lua_pushvalue(l, -1); -- now 2 copies of closure on top of stack
r = luaL_ref(l, LUA_REGISTRYINDEX); --one consumed, put into registry, 1 left
--calling Call()
--this C API call has got a new piece of stack
-- which does not contain that leftover of closure copy!
lua_rawseti(l, LUA_REGISTRYINDEX, r); --overwrite Lua registry entry with what?
lua_call(l, 0, 0); --What the heck are we calling now?
Thanks siffijoe and Etab Reisner for clarification about that new piece of stack.
What You should be doing:
I still don't really understand what actually are You trying to do, but in Your Lua code sample to execute properly (closure gets called by Call(), You should retrieve the closure before executing instead of overwriting with something which does not exist on top of the Lua stack. Something like this:
int Lua_Call(lua_State* l){
lua_rawgeti(l, LUA_REGISTRYINDEX, r); // <--- retrieve closure from registry!
lua_call(l, 0, 0); // <--- consider using lua_pcall()
return 0; // <--- the call does not leave anything useful on the stack.
}
NOTE: decide, which C API functions of Yours returns something, which ones does not. And change the return value to proper one.
Reference: luaL_ref(), lua_rawgeti(), lua_pcall() and misused lua_rawseti().

Working with lua objects in c++

I want to make something like this:
1. Create object in Lua
2. Get this object to C++
3. Perform some method on this object passing it from C++
Now I have this in Lua:
Account = {balance = 0}
function Account.Create(name)
local a = Account:new(nil, name);
return a;
end
function Account:new (o, name)
o = o or {name=name}
setmetatable(o, self)
self.__index = self
return o
end
function Account:Info ()
return self.name;
end
Code in C++
//get Lua object
lua_getglobal (L, "Account");
lua_pushstring(L, "Create");
lua_gettable(L, -2);
lua_pushstring(L, "SomeName");
lua_pcall(L, 1, 1, 0);
const void* pointer = lua_topointer(L, -1);
lua_pop(L, 3);
//then I want to perform some method on object
lua_getglobal (L, "Account");
lua_pushstring(L, "Info");
lua_gettable(L, -2);
lua_pushlightuserdata(L,(void*) pointer );
lua_pcall(L, 0, 1, 0);
//NOW I GET "attempt to index local 'self' (a userdata value)'
const char* str = lua_tostring(L, -1);
...etc...
Do you what I made wrong ? How can I get this Lua object to C++ ?
const void* pointer = lua_topointer(L, -1);
Lua tables are not C objects. They're not void*s. The lua_topointer documentation says that the function is mainly for debugging purposes. You're not debugging anything.
Lua tables can only be accessed through the Lua API. You can't just get a pointer to a Lua table or something. Instead, what you need to do is store the Lua table in a place, and then retrieve it from that location when you want to access it. The typical place for storing this sort of data is the Lua registry. It's inaccessible from Lua code; only the C-API can talk to it.
Generally, you'll have some table stored in the registry that contains all of the Lua values that you are currently holding. That way, your use of the registry won't bash someone else's use of it.

Lua: getting global function failing after loading file

I'm attempting to call a function inside of a lua file called test2.lua
This is the contents of test2.lua:
function abc(path)
t = {}
table.insert(t, "a")
return t
end
As you can see it takes a single input and returns a string.
Here is my C code. It's pretty simple. However my call getglobal in order to call that function does not work... lua_getglobal says it isn't a function when I test it... Any reason why this is? Shouldn't abc be a global function returnable inside of the source file? Why then does it only find nil for this global?
L = lua_open();
luaL_openlibs(L);
luaL_loadfile(L, "src/test2.lua");
lua_getglobal(L, "abc");
lua_pushstring(L, "coollll");
int error = 0;
if ((error = lua_pcall(L, 1, 1, 0)) == 0)
{
std::cout << "cool";
}
EDIT:
calling lua_getglobal is causing my program to break control regardless of using loadfile or dofile... any idea why?
lua_getglobal crashing program
The function luaL_loadfile() reads, parses, and compiles the named Lua file. It does not execute any of its content. This is important in your case because the statement function abc(path)...end has no visible effect until it is executed. The function keyword as you've used it is equivalent to writing
abc = function(path)
t = {}
table.insert(t, "a")
return t
end
In this form, it is clearer that the variable named abc is not actually assigned a value until the code executes.
When luaL_loadfile() returns, it has pushed an anonymous function on the top of the Lua stack that is the result of compiling your file. You need to call it, and lua_pcall() will do the trick. Replace your reference to luaL_loadfile() with this:
if (luaL_loadfile(L, "src/test2.lua") || lua_pcall(L, 0, LUA_MULTRET, 0)) {
// do something with the error
}
At this point, test2.lua has been executed and any functions it defined or other global variables it modified are available.
This is a common enough idiom, that the function luaL_dofile() is provided to load and call a file by name.
There is a second, more subtle issue in your code as presented. The function abc() uses a variable named t, but you should be aware that t as used is a global variable. You probably meant to write local t = {} at the top of abc().
It's not enough to call luaL_loadfile: this puts a chunk onto the stack. Either follow up with luaL_[p]call to execute the chunk (thus making the function available), or use luaL_dofile.

How to read Lua table return value from C++

I have a Lua function that returns table (contains set of strings)
the function run fine using this code:
lua_pushstring (lua, "funcname");
lua_gettable (lua, LUA_GLOBALSINDEX);
lua_pushstring(lua, "someparam");
lua_pcall (lua, 1, 1, 0);
the function returns a table. How do I read it's contents from my C++ code?
If you are asking how to traverse the resulting table, you need lua_next (the link also contains an example). As egarcia said, if lua_pcall returns 0, the table the function returned can be found on top of the stack.
If the function doesn't throw any errors, then lua_pcall will:
Remove the parameters from the stack
Push the result to the stack
This means that, if your function doesn't throw any errors, you can use lua_setfield right away - lua_pcall will work just like lua_call:
lua_pushstring (lua, "funcname");
lua_gettable (lua, LUA_GLOBALSINDEX);
lua_pushstring(lua, "someparam");
lua_pcall (lua, 1, 1, 0);
lua_setfield(L, LUA_GLOBALSINDEX, "a"); /* set global 'a' */
would be the equivalent of:
a = funcname(someparam)