Lua Anonymous function storing in C++ - 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().

Related

how to create lua c++ wrapper from c++

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.

Accessing Lua variable in function environment from C++

This is probably an easy question, but I am stumped. This is for Lua 5.1.
I have a script which runs in its own environment. In that environment, I have a variable called "plugin" I set from C++ like so:
lua_getfield(L, LUA_REGISTRYINDEX, getScriptId()); // Put script's env table onto the stack -- env_table
lua_pushstring(L, "plugin"); // -- env_table, "plugin"
luaW_push(L, this); // -- env_table, "plugin", *this
lua_rawset(L, -3); // env_table["plugin"] = *this -- env_table
lua_pop(L, -1); // Cleanup -- <<empty stack>>
Before running my Lua script, I set the function environment like so:
lua_getfield(L, LUA_REGISTRYINDEX, getScriptId()); // Push REGISTRY[scriptId] onto stack -- function, table
lua_setfenv(L, -2); // Set that table to be the env for function -- function
When my script runs, it can see and interact with the plugin variable, as expected. So far, so good.
At one point, the Lua script calls a C++ function, and in that function, I want to see if the plugin variable is set.
I have tried many many things, and I can't seem to see the plugin variable. Here are but 4 things I tried:
lua_getfield(L, LUA_ENVIRONINDEX, "plugin");
bool isPlugin = !lua_isnil(L, -1);
lua_pop(L, 1); // Remove the value we just added from the stack
lua_getfield(L, LUA_GLOBALSINDEX, "plugin");
bool isPlugin2 = !lua_isnil(L, -1);
lua_pop(L, 1); // Remove the value we just added from the stack
lua_getglobal(L, "plugin");
bool isPlugin3 = !lua_isnil(L, -1);
lua_pop(L, 1); // Remove the value we just added from the stack
lua_pushstring(L, "plugin");
bool isPlugin4 = lua_isuserdata(L, -1);
lua_pop(L, 1);
Unfortunately, all the isPlugin variables return false. It is as if the C++ function called from Lua cannot see a variable set in a Lua environment.
Any idea how I can see the plugin variable from C++?
Thanks!
Every function in Lua has it's own environment. They don't inherit the environment of whomever calls them. So if your C++ function doesn't use the environment that has this plugin variable, then it won't see it.
You could pass the environment to the C function as part of the closure (see lua_pushcclosure). I don't know the kind of setup you have, but I can see three ways this can pan out:
1) Your C function is registered in the same environment as the function - good, will work.
2) Your C function is registered in the global environment but the Lua functions which will call it all reside in one specific environment - will still work if the environment exists when the function is registered (so it can be added to the closure).
3) Your C function is registered in the global environment and can be called by different Lua functions working in different environments - will not work anymore.
If it's 2 or 3, there might be no drawbacks if you change the implementation to use variant 1.
Edit: Alright, so that won't work. There is a way to obtain under-the-hood information if you are willing to stray a bit from the Lua API. DISCLAIMER: I am working with 5.2, so I am trying to adapt my methods for 5.1. I could not test this, and it might not work.
First you will need to #include "lstate.h"
This is the lua_State structure in 5.1:
struct lua_State {
CommonHeader;
lu_byte status;
StkId top; /* first free slot in the stack */
StkId base; /* base of current function */
global_State *l_G;
CallInfo *ci; /* call info for current function */
const Instruction *savedpc; /* `savedpc' of current function */
StkId stack_last; /* last free slot in the stack */
StkId stack; /* stack base */
CallInfo *end_ci; /* points after end of ci array*/
CallInfo *base_ci; /* array of CallInfo's */
int stacksize;
int size_ci; /* size of array `base_ci' */
unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask;
lu_byte allowhook;
int basehookcount;
int hookcount;
lua_Hook hook;
TValue l_gt; /* table of globals */
TValue env; /* temporary place for environments */
GCObject *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
struct lua_longjmp *errorJmp; /* current error recover point */
ptrdiff_t errfunc; /* current error handling function (stack index) */
};
Let's assume L is your lua_State*.
As you can see, L->ci holds the current callinfo, and the callinfo array is contained between L->base_ci and L->end_ci.
So the Lua function which called your C function is situated at (L->end_ci-2) (which should be the same as (L->ci-1)), and its stack id (StkId) is (L->end_ci-2)->func.
We can trick the Lua API into letting you work with stack ids which are below the current calling function by doing something like this:
StkId saved = L->base;
L->base = L->base_ci->base;
int idx = (L->end_ci-2)->func - L->base+1;
lua_getfenv(L, idx);
L->base = saved;
The environment table should be on top of the stack now.
Edit: The Lua API checks for a valid index are a bit tricky. This should fool them.

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.

Call Lua function from C++, missing argument

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)

How should I bind lua functions to C++ functions?

I have a class called Entity, which has many functions like onPickup, onDrop, onUse etc. What I want to do is, write a script that defines all of these functions and make them callable from the C++ functions. So the functions defined in C++ would just be calling their corresponding Lua functions that have some functionality.
But here's the problem, I want every script that I write, for every Entity in the program to be working in it's own scope.
I'm using LuaBind, and I have no prior experience with Lua, so I'm a little lost here.
I don't use lua bind but this may help. The idea is to register the lua functions in your C++ class and keep a reference to the lua function in your C++ class.
To define a lua function that is callable from C/C++ I use luaL_ref to store a reference to the callback function in my C++ object.
// a little helper function
template <typename T>
T *Lua_getUserData(lua_State *L) {
assert(lua_isuserdata(L, 1) == 1);
T **v = (T **) lua_touserdata(L, 1);
assert(v != NULL);
return *v;
}
int lua_FormRegisterMethods(lua_State *L) {
Entity *f = Lua_getUserData<Entity>(L);
assert(lua_istable(L, 2) == 1); // check the next parameter is a table
lua_pushvalue(L,2); // dup the table
f->LuaTable = luaL_ref(L, LUA_REGISTRYINDEX); // keep a reference to the table
lua_getmetatable(L, 2); // get the metatable
lua_pushstring(L, "OnClick");
lua_rawget(L, -2); // get the OnClick Lua Function
f->LuaMethod = luaL_ref(L, LUA_REGISTRYINDEX); // save a reference to it
return 0;
}
and then you can get the lua method in your C++ event
lua_rawgeti( LuaInstance->L, LUA_REGISTRYINDEX, LuaMethod );
assert(lua_isfunction(LuaInstance->L, -1) == 1);
now you can call this function with self set to the table you saved earlier. hth
You can call a Lua function with, e.g.
int callLuaFunction(lua_State* lua_state) {
return luabind::call_function<int>(lua_state, "myluafunction", param1);
}
if the Lua function returns an int and takes 1 parameter.
I'm pretty sure you can make as many lua_State's as you want. Just pass the correct one for the entity into call_function.
To fully implement this the way you will probably want to will require digging around a bit in some of the more esoteric bits of Lua. It is well worth the time though. I'll show a very trimmed down version of how I have handled this. Be warned, there are a lot of little bits all working together here - mainly saving and calling saved functions and using c++ objects as Lua user data.
First we need a c++ class which will store events handlers (lua functions) as lua references which are simple ints. I am using an array here but you could use whatever makes sense. The main thing happening here is that you want to be able to call a lua function which is referred to by the int reference.
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <string>
#include <iostream>
#include <assert.h>
using namespace std;
enum enum_event_types {
ON_USE, ON_DROP, ON_WHATEVER, EVENT_COUNT
};
class Entity {
private:
int events[EVENT_COUNT];
public:
lua_State* lua;
void setEventHandler(int event, int ref) {
assert(event < EVENT_COUNT);
events[event] = ref;
}
void callEventHandler(int event) {
int error;
assert(event < EVENT_COUNT);
// to call the function we need to get it from the registry index
lua_rawgeti(lua, LUA_REGISTRYINDEX, events[event]);
error = lua_pcall(lua, 0, 0, 0); // use protected call for errors
if (error) {
printf("error: %s", lua_tostring(lua, -1));
lua_pop(lua, 1);
}
}
};
Now you want to expose your Entity class to Lua. If you are not familiar with how this is done there is a good article here. Essentially what is going on is that we are setting the user data returned from Entity.new() to a pointer to a pointer. This is so Lua does not garbage collect your object. Then create a meta table for "Entity" which will
hold all of the methods exposed to Lua.
int L_newEntity(lua_State* L) {
Entity **e = (Entity **)lua_newuserdata(L, sizeof(Entity *));
*e = new Entity();
(*e)->lua = L;
lua_getglobal(L, "Entity");
lua_setmetatable(L, -2);
return 1;
}
int L_setOnUse(lua_State* L) {
Entity** e = (Entity**) lua_touserdata(L, 1);
lua_pushvalue(L, 2);
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
(*e)->setEventHandler(ON_USE, ref);
return 0;
}
// this will be exposed to Lua as a table called Entity
static const luaL_Reg L_entityMethods[] = {
{"new", L_newEntity},{"setOnUse", L_setOnUse},{NULL, NULL}
};
Now set up the Lua state and create the Entity table and create a test. The test will create an Entity and set its event handler to a Lua function passed to it. Finally test that the Lua function is being called by the c++ object.
int main() {
Entity** e;
int error;
lua_State* L=lua_open();
luaL_openlibs(L);
luaL_register(L, "Entity", L_entityMethods);
lua_pushvalue(L,-1);
lua_setfield(L, -2, "__index");
lua_pop(L, 1);
luaL_loadstring(L,
"e = Entity.new(); "
"e:setOnUse(function()"
" print('Some of them want to use you')"
"end);");
error = lua_pcall(L, 0, 0, 0);
if (error) {
printf("error: %s", lua_tostring(L, -1));
lua_pop(L, 1); /* errors must be popped from stack */
}
lua_getglobal(L, "e");
if (lua_isuserdata(L, 1)) {
e = (Entity**) lua_touserdata(L, 1);
(*e)->callEventHandler(ON_USE);
}
return 0;
}
This is far from complete. First of all if you ever need to set an event handler twice you will need to use luaL_unref to clear out the old reference first. Second you will probably want to pass some data about the event which occurred to the event handler. The current event handler does not take any data so gives the user of the api very little to go on. It should probably at least pass a reference to the object which is calling the event. This can be used to create very powerful and usable Apis in Lua. Good luck!