Lua Error Attempt to perform arithmetic on local variable - lua

Here is the function
calc.lua:
function foo(n)
return n*2
end
Here is my LuaJavaCall
L.getGlobal("foo");
L.pushJavaObject(8);
int retCode=L.pcall(1,1,0); // nResults)//L.pcall(1, 1,-2);
String errstr = L.toString(-1); // Attempt to perform arithmetic on local variable 'n'
Update: as indicated below I needed to use L.pushNumber(8.0) instead of L.pushJavaObject()

Try using L.pushNumber instead of L.pushJavaObject like this:
L.getGlobal("foo");
L.pushNumber(8.0);
int retCode = L.pcall(1,1,0);
String errstr = L.toString(-1);
Lua probably sees JavaObject as a type of 'userdata' in which case there are no predefined operations for it; Lua won't know what to do with a JavaObject * 2 since you didn't define how to handle it.
OTOH, Lua does know how to handle a number since that's a builtin primitive type. For the code snippet you presented, pushing a number would be the least painful way to get it working instead of writing extra code that tells Lua how to work with numbers wrapped inside a JavaObject.

Related

how to convert a function to string in Lua?

How to output the contents of a function?
function a()
print("Hello,World")
end
print(func_toString(a))
I hope the result of func_toString(a) could be
function a()
print("Hello,World")
end
or just
print("Hello,World")
It is assumed that the source code is executed directly without precompiling or embedding.
How to do this?
well, it's not completely impossible, the code in some cases can be read from a lua file, for example:
function a()
print("Hello,World")
end
local function get_source_code(f)
local t = debug.getinfo (f)
if t.linedefined < 0 then print("source",t.source); return end
local name = t.source:gsub("^#","")
local i = 0
local text = {}
for line in io.lines(name) do
i=i+1
if i >= t.linedefined then text[#text+1] = line end
if i >= t.lastlinedefined then break end
end
return table.concat(text,"\n")
end
print( get_source_code(a) )
maybe that will be enough.
This is not possible from within the running Lua program.
Lua provides the debug library to inspect functions and variable. This allows you to obtain the source (the path or string where the function is defined) and the line range on which the function is defined. In the vast majority of cases this might actually be enough: Just find the first occurrence of function(...) on the first line and the first occurrence of end on the last line, then string.sub the relevant portion. This is however rather error prone; consider e.g.
function a() function b() end end
a()
func_toString(a)
since both functions are on the same line, you can't distinguish them - the debug library only provides you line info, nothing more. You could try to distinguish them by their signature since hacks exist to obtain the method signature, but that would fail here as well since both functions have the same signature. You could try gsubing them out based on their names, but remember that functions can be anonymous in Lua.
Lua also provides the string.dump function to obtain the bytecode of a function. I highly doubt that this is of any use to you; theoretically you could decompile it to get back a "Lua" representation of what the function does, but it would hardly be recognizable or readable.

How to modify a metatable which was created by C API?

I want to add some methods or properties to a lua object witch metadata was created by C API. I can't add property in normal way, for example:
local foo = libc.new()
foo.bar = "hello"
it say:
Failed to run script: attempt to index a libc_meta value (local 'foo')
So I think maybe need to modify metatable, so I change my code:
local foo = libc.new()
local mt = getmetatable(foo)
foo[bar] = "hello"
setmetable(foo, mt)
Unfortunately, it still doesn't work.
Failed to run script: bad argument #1 to 'setmetatable' (table expected, got libc_meta)
So how can I add methods or properties to this 'foo'?
BTW, c code is here:
static int libc_new(lua_State *L) {
...
lua_lib_space *libc = lua_newuserdata(L, sizeof(*libc));
libc->L = L;
libc->cb_enter = cb_enter;
libc->cb_leave = cb_leave;
luaL_getmetatable(L, "libc_meta");
lua_setmetatable(L, -2);
lib_space *lib = lib_new(enter, leave, libc);
libc->space = lib;
return 1;
}
Userdata is meant to be created by C, manipulated by C code, and for only the purposes that C code intends. Lua can talk to it, but only in the ways that C allows it to. As such, while userdata can have a metatable (and those metamethods are the only way Lua can "directly" interact with the userdata), only C functions (and the debug library, but that's cheating) can directly manipulate that metatable. Lua is an embedded language, and C has primacy; if some C library wants to shut you out, it can.
What you can do is take the userdata and stick it in a table of your own, then give that table a metatable. In your __index metamethod, if you have an override or new method for a particular key, then you forward the accesses to that. Otherwise, it will just access the stored userdata.
However, if what you get in the userdata is a function, then you may have a problem. See, most userdata functions take the userdata as a parameter; indeed, most are meant to be called via "ud:func_name(params). But if thatud` is actually the table wrapper, then the first parameter passed to the function will be the wrapper, not the userdata itself.
That poses a problem. When the thing you get from the userdata is a function, you would need to return a wrapper for that function which goes through the parameters and converts any references to the wrapper table into the actual userdata.

Modifying Lua Functions

I am trying to mod a Lua game (CtGW). There is a function, engine:GetSavegames, which returns an array of strings, and I cannot access. I need to modify the returned results. I tried the following, but recieved a "function arguments expected near 'engine'" error.
getsaves = engine:GetSavegames
engine:GetSavegames = function()
return getsaves()
end
engine:GetSavegames is only valid syntax for method invocation and not for assignments. As #ChrisBeck wrote in the comment, you need to use engine.GetSavegame, but you also need to pass any parameters you can get as those will include the actual object.
Something like this may work:
local getsaves = engine.GetSavegames
engine.GetSavegames = function(...)
return getsaves(...)
end
This operation is usually called monkeypatching.

Calling Lua from C

I'm trying to call a user-defined Lua function from C. I've seen some discussion on this, and the solution seems clear. I need to grab the index of the function with luaL_ref(), and save the returned index for use later.
In my case, I've saved the value with luaL_ref, and I'm at a point where my C code needs to invoke the Lua function saved with luaL_ref. For that, I'm using lua_rawgeti as follows:
lua_rawgeti(l, LUA_REGISTRYINDEX, fIndex);
This causes a crash in lua_rawgeti.
The fIndex I'm using is the value I received from luaL_ref, so I'm not sure what's going on here.
EDIT:
I'm running a Lua script as follows:
function errorFunc()
print("Error")
end
function savedFunc()
print("Saved")
end
mylib.save(savedFunc, errorFunc)
I've defined my own Lua library 'mylib', with a C function:
static int save(lua_State *L)
{
int cIdx = myCIndex = luaL_ref(L, LUA_REGISTRYINDEX);
int eIdx = luaL_ref(L, LUA_REGISTRYINDEX);
I save cIdx and eIdx away until a later point in time when I receive some external event at which point I would like to invoke one of the functions set as parameters in my Lua script. Here, (on the same thread, using the same lua_State*), I call:
lua_rawgeti(L, LUA_REGISTRYINDEX, myCIndex);
Which is causing the crash.
My first suggestion is to get it working without storing the function in C at all. Just assign your function to a global in Lua, then in C use the Lua state (L) to get the global, push the args, call the function, and use the results. Once that's working, you've got the basics and know your function is working, you can change the way you get at the function to use the registry. Good luck!
As #Schollii mentioned, I was making this call after doing a lua_close(L).

How can I load an unnamed function in Lua?

I want users of my C++ application to be able to provide anonymous functions to perform small chunks of work.
Small fragments like this would be ideal.
function(arg) return arg*5 end
Now I'd like to be able to write something as simple as this for my C code,
// Push the function onto the lua stack
lua_xxx(L, "function(arg) return arg*5 end" )
// Store it away for later
int reg_index = luaL_ref(L, LUA_REGISTRY_INDEX);
However I dont think lua_loadstring will do "the right thing".
Am I left with what feels to me like a horrible hack?
void push_lua_function_from_string( lua_State * L, std::string code )
{
// Wrap our string so that we can get something useful for luaL_loadstring
std::string wrapped_code = "return "+code;
luaL_loadstring(L, wrapped_code.c_str());
lua_pcall( L, 0, 1, 0 );
}
push_lua_function_from_string(L, "function(arg) return arg*5 end" );
int reg_index = luaL_ref(L, LUA_REGISTRY_INDEX);
Is there a better solution?
If you need access to parameters, the way you have written is correct. lua_loadstring returns a function that represents the chunk/code you are compiling. If you want to actually get a function back from the code, you have to return it. I also do this (in Lua) for little "expression evaluators", and I don't consider it a "horrible hack" :)
If you only need some callbacks, without any parameters, you can directly write the code and use the function returned by lua_tostring. You can even pass parameters to this chunk, it will be accessible as the ... expression. Then you can get the parameters as:
local arg1, arg2 = ...
-- rest of code
You decide what is better for you - "ugly code" inside your library codebase, or "ugly code" in your Lua functions.
Have a look at my ae. It caches functions from expressions so you can simply say ae_eval("a*x^2+b*x+c") and it'll only compile it once.

Resources