I have strange problem, with calling Lua function from C++.
I have in Lua:
Player =
{
Number = 0.43,
Text = "SomeText",
}
function Player:Func(a, b)
return (a * b);
end
Before lua_pcall my stack looks:
table
function
3
4
I call this function with:
lua_pcall(L, 2, 1, 0)
And I get error from Lua:
attempt to perform arithmetic on local 'b' (a nil value)
When I change in Lua script
return (a * b);
to
return a;
There is no error, but from lua_tonumber(L, -1); I get value 4 (my second argument in C:/), so it looks that my second argument in C is first in Lua.
Do you know what I made wrong in my code ?
How I construct stack:
lua_getglobal (L, "Player");
lua_pushstring(L, "Func");
lua_gettable(L, -2);
lua_pushnumber(L, 3.0);
lua_pushnumber(L, 4.0);
Ben's comment is the key - Read the Object-oriented programming section in "Programming In Lua", page 150.
http://www.lua.org/pil/16.html
The effect of the colon is to add an extra hidden parameter in a
method definition and to add an extra argument in a method call.
So you need to push an "Account" object as the first parameter, or (more easily in this case) change function Player:Func(a, b) to function Player.Func(a, b)
Related
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);
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().
I have some lua 'objects' that are wrappers to C++ objects, they hold a local reference to the c++ object and call it.
Now i want some functions in C++ return those wrappers, so i need to call this lua function and then set the C++ object on it.
I experience crashes and i suspect that i am not handling the lua stack right. For example, if i ask for lua_top before exiting a function that creates the wrapper + c++ object, i get 5 as result, shouldn't it be 1 if i return 1 object?
So here is what i do, maybe i am doing it wrong, maybe there is a better way to do this.
c++, .h:
#define gLuaGet(L, var, type) \
if (lua_istable(L, 1)) {\
lua_getfield(L, 1, "CObj");\
lua_replace(L, 1);\
}\
type& var = *(type*)lua_touserdata(L, 1);
#define gLuaCreate(L, type) new (lua_newuserdata(L, sizeof(type))) type();
class MyObject {
public:
MyObject();
int somefunc();
};
int MyObjectCreate(lua_State *L);
int MyObjectCallSomefunc(lua_State *L);
c++, .cpp:
int MyObject::somefunc() {
std::cerr << "in c++ function" << std::endl;
return 123;
}
int MyObjectCreate(lua_State *L) {
gLuaCreate(L, MyObject);
return 1;
}
int MyObjectCallSomefunc(lua_State *L) {
gLuaGet(L, obj, MyObject);
int r = obj.somefunc();
lua_checkstack(L, 1);
lua_pushnumber(L, r);
return 1;
}
lua wrapper:
function MyObject(donotinit)
self = {}
self.CObj = nil
if (donotinit == nil) then
self.CObj = MyObjectCreate()
end
self.setCObject = function(obj)
self.CObj = obj
end
self.somefunc = function()
return MyObjectCallSomeFunc(self)
end
return self
end
Now i want some other wrapper to return a MyObject that is created within c++, so here is the c++ code that is called from the new wrapper (for better readabiliy i removed the sanity checks on lua_pcall):
int returnLuaMyObject(lua_State *L) {
gLuaGet(L, obj, MyOtherObject);
MyObject *myObject = obj.getMyObject(); // get c++ part
lua_getglobal(L, "MyObject"); // create lua part
lua_pushnumber(L, 1); // and tell it not to initialize the self.CObj
lua_pcall(L, 1, 1, 0);
lua_getfield(L, -1, "setCObject"); // call the setCObject function
lua_pushlightuserdata(L, myObject); // give c++ object as param
lua_pcall(L, 1, 0, 0);
// at this point lua_gettop(L); returns 5, can this be correct?
return 1;
}
Well, if i call this function via a lua wrapper now a couple of times, everything seems fine, but if i call it lets say 50 times in a while loop, its crashing on random times (but always on the same c++ line)
Am i doing something wrong here? Is it OK for the lua stack top to be 5 at this point, where it only returns one object?
This is what your Lua stack will look like after each function/macro call, if I'm reading this correctly
int returnLuaMyObject(lua_State *L) {
// arg
gLuaGet(L, obj, MyOtherObject); // arg.CObj
MyObject *myObject = obj.getMyObject();
lua_getglobal(L, "MyObject"); // arg.CObj _G.MyObject
lua_pushnumber(L, 1); // arg.CObj _G.MyObject 1
lua_pcall(L, 1, 1, 0); // arg.CObj obj
lua_getfield(L, -1, "setCObject"); // arg.CObj obj obj.setCObject
lua_pushlightuserdata(L, myObject); // arg.CObj obj obj.setCObject myObject
lua_pcall(L, 1, 0, 0); // arg.CObj obj
// at this point lua_gettop(L); returns 2.
// If you end this function with return 1, only obj is returned
// to Lua, everything else is discarded.
return 1;
}
(For what it's worth, when writing Lua code I religiously put comments like that on every single line that messes with the Lua stack so I always know what I'm operating on. Once you memorize the side effects of Lua function it makes bug finding very easy)
This should be fine assuming that returnLuaMyObject is being called from Lua. If you're calling it in a loop in C++ your stack is going to get messed up since it's left with two things on the stack and some of your functions are hardcoded to operate on index 1.
A better way to do this is to do what Cubic suggested and use some templates rather than macros. You should also avoid using hardcoded indexes when possible so that you can reuse your functions in situations where the object you're interested in is in a difference spot on the stack. For example, your gLuaGet should take an index as an argument so that you can use it anywhere. (I'd also get rid of the obj argument and drop the entire last line of the macro, it makes it unclear where the the variable obj is being declared.
I wrote a library for myself (coincidentally called LuaWrapper, located here) which lets you do what you want without a lot of hassle. You can use luaW_to and luaW_push to push and get pointers from
Lua just like they were numbers or strings. I'm just throwing it out there because I like it better than the suggestion of Luabind or toLua++
The top of the stack in Lua is -1, not 1 (or lua_gettop(state)). Also, you should really use templates rather than macros for this. Or better yet, unless you have a reason not to, you could use luabind or tolua++. I'm currently writing something that works essentially the same as luabind, but uses C++11 features to drop the boost dependency, although it's nowhere near completion yet.
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.
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.