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.
Related
I have a C++ program that creates will create a lua_State and invoke custom lua code. Before calling the custom lua function, luaopen_ffi() is called with the lua_State:
luaopen_ffi(lua_state_);
However, when my program execute the custom lua code, it cannot find ffi. I further print out the value of ffi, and sadly it's nil instead:
print(ffi) --- which outputs nil
while other libraries loaded using luaopen does have a non-nil value, for instance
print(io) --- outputs table: 0x400af268
I further checked the source code of luaopen_ffi, it says it does not create a global ffi namespace based on its comment:
LUALIB_API int luaopen_ffi(lua_State *L) {
CTState *cts = lj_ctype_init(L);
settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1)));
cts->finalizer = ffi_finalizer(L);
LJ_LIB_REG(L, NULL, ffi_meta);
/* NOBARRIER: basemt is a GC root. */
setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
LJ_LIB_REG(L, NULL, ffi_clib);
LJ_LIB_REG(L, NULL, ffi_callback);
/* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */
settabV(L, lj_tab_setstr(L, cts->miscmap, &cts->g->strempty), tabV(L->top-1));
L->top--;
lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */
lua_pushliteral(L, LJ_OS_NAME);
lua_pushliteral(L, LJ_ARCH_NAME);
LJ_LIB_REG(L, NULL, ffi); /* Note: no global "ffi" created! */
ffi_register_module(L);
return 1;
}
I also tried ffi = require("ffi") and it does not work :(.
So can I know how can I use ffi features after calling luaopen_ffi? Or luaopen_ffi is not the correct way?
If you want a global named ffi, try this:
luaopen_ffi(lua_state_);
lua_setglobal(lua_state_ ,"ffi");
It seems that luaopen_ffi leaves the table on the stack, as is usual in Lua modules.
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'm implementing Lua as a script language into a Windows application. Due to the application's structure, printout isn't using streamed io, such as stdout and stderror.
I have managed to override the Lua print to fit into my structure...
lua_register(L,"print", cs_print);
...but how do I override all error an debug printouts without using streams? I need to handle this in a function (similar to print).
The only place where Lua writes to stderr is in the panic function that luaL_newstate installs. If you're embedding Lua into your application, make sure you start Lua from a protected call and no panic will ever occur. See http://www.lua.org/source/5.2/lua.c.html#main for ideas.
After a lot of Google I came up with this solution to fetch compiler and runtime error messages as well to redirect the standar Lua print function.
I use C++ Builder but I think it can be useful for anyone looking for the same answer.
The script is running in a TScriptLua object instance and to map a Lua state against the correct script instance, I use a std::map list to look up the object pointer.
// list for mapping Lua state with object pointers.
static std::map<lua_State*,TScriptLua*> LuaObjMap;
Next is an inline function to get the object pointer from a Lua state pointer.
extern "C" {
// Inline to map Lua state pointer to object pointer
static inline TScriptLua* GetScriptObject(lua_State* L) {
return LuaObjMap.find(L)->second;
}
This function will replace the standard Lua print function. The object pointer (f) has a member function in its base class called Out() that will output a char buffer in the associated window control.
// New Lua print function
static int cs_print (lua_State *L) {
// Map Lua state to object
TScriptLua* f = GetScriptObject(L);
if (f) {
int count = lua_gettop(L);
for (int i=1; i <= count; ++i) {
const char *str = lua_tostring(L, i); // Get string
size_t len = lua_rawlen(L,i); // Get string length
// Output string.
f->Out(str,len);
}
}
return 0;
}
This is my error print routine that will display the compiler/runtime error. As for the Lua print function, the f->Out is used again to print the error message.
// Error print routine
static int cs_error(lua_State *L, char *msg) {
// Map Lua state to object
TScriptLua* f = GetScriptObject(L);
// Get error message
AnsiString m = String(msg) + " " + String(lua_tostring(L, -1));
// "print" error message
f->Out(m.c_str(),m.Length());
// Clenaup Lua stack
lua_pop(L, 1);
return 0;
}
} // <--- End extern C
Here is the actual load and run member. After the new Lua state has been created it is associated with this object in the mapping list. Then it loads the script from a Rich edit control with luaL_loadbuffer(), checks for compiler errors and runs the compiled script with lua_pcall().
void __fastcall TScriptLua::Compile(void) {
// Create new Lua state
lua_State *L = luaL_newstate();
// Store mapping Lua state --> object
LuaObjMap.insert( std::pair<lua_State*,TScriptLua*>(L,this) );
// Override Lua Print
lua_register(L,"print", cs_print);
// Load and compile script
AnsiString script(Frame->Script_RichEdit->Text);
if (luaL_loadbuffer(L,script.c_str(),script.Length(),AnsiString(Name).c_str()) == 0) {
if (lua_pcall(L, 0, 0, 0)) // Run loaded Lua script
cs_error(L, "Runtime error: "); // Print runtime error
} else {
cs_error(L, "Compiler error: "); // Print compiler error
}
// Close Lua state
lua_close(L);
// Remove Lua --> object mapping
LuaObjMap.erase( LuaObjMap.find(L) );
}
This isn't my final solution, but it does the trick so far. I think the best thing is to write stream handling into the TScriptLua object so I can register it directly into Lua.
I want to how we can expose properties to lua library.
luaL_openlib( L, kName, kVTable, 1 ); // leave "library" on top of stack
With this, I am able to expose only functions as kVTable refers to luaL_Reg
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
Eg: With the above code. I can do following.
local myLib = require "plugin.myLib"
myLib.newFunc();
However, I want to expose Lua Table to the library as CONSTANTS variable.
myLib.CONSTANTS.SOME_CONST_1
myLib.CONSTANTS.SOME_CONST_2
etc. Please let me know how can I expose lua Table from my library as property.
As luaL_openlib leaves the library table on top on the stack, you can use regular C API to add new fields and subtables to it:
luaL_openlib( L, kName, kVTable, 1 ); // leaves "library" on top of stack
lua_pushstring(L, "CONSTANTS");
lua_newtable(L); // this will be CONSTANTS subtable
lua_pushstring(L, "SOME_CONST_1");
lua_pushnumber(L, 42); // SOME_CONST_1 value
lua_settable(L, -3); // sets SOME_CONST_1
lua_pushstring(L, "SOME_CONST_2");
lua_pushnumber(L, 12345); // SOME_CONST_2 value
lua_settable(L, -3); // sets SOME_CONST_2
lua_settable(L, -3); // sets CONSTANTS table as field of the library table
return 1;
If you use C++, you can use a binding library, such as the header-only luabridge to bind some data to named tables in Lua. Transforming your example into LuaBridge, call this function after you initialize your Lua state:
void register_constants (lua_State* L) {
luabridge::getGlobalNamespace(L)
.beginNamespace("myLib")
.beginNamespace("CONSTANTS")
.addVariable("SOME_CONST_1",&some_const_1,false/*read-only*/)
.addVariable("SOME_CONST_2",&some_const_2,false/*read-only*/)
.endNamespace()
.endNamespace()
;
}
...
lua_State* L=lua_open();
register_constants(L);
...
you can access the constants as your last code snippet
Caveat, lector, because Lua C API is, well, C API.
The whole burden with loadlib and friends was because functions are much harder to pass using C (C funcions aren't first class values). So my best bet would be to set all those constants using regular stack API.
In general, it is supposed to be used to exchange runtime data, of course, but there's no inherent reason why you shouldn't be able to fill your tables with that when loading the module.
I have a c++ class that organizes parts on a screen that can be drawn to, called Canvases.
I want to create those canvasses from Lua (which I already do), the C++ code keeps track of them and renders them to the screen.
But to draw into a canvas, I want to be able to make that available from LUA, so what I want is to say something like this:
local c1 = foo.createCanvas("test", 60, 60, 300, 200);
c1:onPaint = function(params)
self:clear(1, 0, 0, 1);
self:moveTo(10, 10);
self:lineTo(100, 100);
end
createCanvas are functions inside foo, clear, moveTo, lineTo are function of the canvas object that is created by createCanvas.
So now, when foo starts rendering everything, it should see that an onPaint function has been defined in canvas "test" and that this function should first be called before rendering to screen.
How should I do this?
the canvas is a lua metatable object in C++ with a __index and __newindex declared. I presume that I should take the __newindex to find out that onPaint will be defined. How can I get this function?
boost::shared_ptr<Canvas> **pppCanvas = (boost::shared_ptr<Canvas> **)luaL_checkudata(L, 1, "Canvas");
std::string key = lua_tostring(L, 2);
if (key == "onPaint")
{
// sometype x = lua_tofunction(L, 3);???
}
else
luaL_error(L, "Canvas - member '%s' is not defined", key.c_str());
return 0;
So what type should I use, what function should I use to get this function to?
And then, how will I call this lua-function? And how will I find out if the function has been defined in the first place?
EDIT:
I found this topic: click
It shows how to make a reference to a lua-function and ask it back later.
The only problem now is: luaL_ref doesn't take a stack index, so I don't know how to take the function from the stack in my above __newindex function.
My problem is solved now (can't seem to set this problem to solved because of low reputation) because I actually need the last item on the stack. But I would like to know if anyone knows how I can take another item in the stack.
Anyway: PROBLEM SOLVED
D.
Seems you can use lua_call to fulfill your need. Note that swig does not support director in lua afaik and is thus not an option.
EDIT:
Updated according to your example:
lua_getfield(L, LUA_GLOBALSINDEX, "myLuaFunctionToCall"); /* function to be called */
lua_pushinteger(L, 3); // parameter is 3
lua_call(L, 1, 1); //call with 1 parameter, 1 result
lua_getfield(L, LUA_GLOBALSINDEX, "myLuaFunctionToCall"); /* function to be called */
lua_Number result = lua_tonumber(L,1)