lua function argument expected near <eof> - c++

I try to use lua in a C++ project. For lua executing I write this:
#include <lua.hpp>
...
luaEngine = luaL_newstate();
luaL_openlibs(luaEngine);
register_results(luaEngine); // For register c++ object in the LUA script as metatable
lua_pushstring(luaEngine, resultsId.c_str());
lua_setglobal(luaEngine, "resultsId");
lua_pushboolean(luaEngine, needReloadModel);
lua_setglobal(luaEngine, "needReload");
...
e = luaL_loadbuffer(luaEngine, script.c_str(), script.size(), NULL);
if(e != 0)
// error message
e = lua_pcall(luaEngine, 0, 1, 0);
if(e != 0)
// error message
...
lua_close(luaEngine);
And the lua script:
local Res = ResUpdateLUA(resultsId)
if current_result == "Normal" or current_result=='-' then
status = 'E'
else
status = 'O'
end
needReload = Res:setShowAnalyte('2320', status)
That didn't work and I've got error message:
[string "?"]:7: function arguments expected near <eof>
But when I add
print(needReload)
at the end of the lua script it works nice. What am I doing wrong?

The error message means that Lua reached the end of the source after seeing Res:s but before seeing (.
I suspect that script.size() is wrong. But I can't explain why adding that line works.

Thank you all for your answers. Yes, that was trouble with script.size() coz when it was replaced to e = luaL_loadbuffer(luaEngine, script.c_str(), strlen(script.c_str()), NULL); that started work fine. Sorry for my stupid question.

Related

How to print errors in lua script without running script?

I'm new using Lua in C++. I have some problem with printing error of script.
My purpose is :
Find errors of syntax, function name using luaL_dofile or luaL_dostring without running code like
build codes in Visual studio.
(When using luaL_loadfile or luaL_loadstring, it just find syntax error like 'a == 1', but can't find function name error like 'prit(a)')
Want to print all errors.(In lua, if there was 2 or more errors, it only prints error that was occurred first)
For example I made lua script like this :
test.lua
function sayHello(name)
print("Hello, " .. name .. "!")
end
for a=0, 10
print(a)
end
sayHello()
and in c++ code :
test.cpp
...
int ret;
ret = luaL_dofile(LuaState, filename);
if(ret != 0) {
cout << "error : " << lua_tostring(LuaState, -1) << endl;
lua_pop(LuaState, 1);
}
I want to print errors like :
lua: test.lua:2: attempt to concatenate local `name' (a nil value)
lua: test.lua:7: `do' expected near `print'
Could anybody teach me?

LuaBridge Indescriptive errors

I use LuaJit and LuaBridge to compile lua code and execute it.
When the lua code throws an error, it's really hard to debug - I don't know what line it happened or what caused it.
This is an example:
[string "1"]:0: bad argument #1 to 'info' (string expected, got table)
in the code:
"function foo(bar)\n"
" logger:info(bar.moo);"
How do I translate [string "1"] to the matching code line?
Can I get a stacktrace?
The lua code is "compiled" with doing string.dump on the text code, and then loading it with luaL_loadbuffer.
Psuedo code that loads and calls the lua function:
int result = luaL_loadstring(L, script.c_str());
auto script_function = luabridge::LuaRef::fromStack(L);
auto string_module = luabridge::getGlobal(L, "string");
auto string_dump = string_module["dump"];
auto code = luabridge::LuaRef_cast<std::string>(string_dump(script_function, strip));
luaL_loadbuffer(L, code.data(), code.size(), std::to_string(current_id++).c_str());
lua_pcall(L, 0, LUA_MULTRET, -1);
auto func_to_call = luabridge::getGlobal(L, "foo");
func_to_call(&bar);
[string "1"] comes from the chunk name you provided here: std::to_string(current_id++).c_str()
Since it doesn't start with # it's treated as the string that was loaded, hence the [string ""] syntax. If you want the error message to treat it as a filename, put # in front of the filename.
And I suspect that the reason the line number is 0 because you told Lua to delete the line numbers, by setting "strip" to true.

LUA embeded in C++ socket.http [error: attempt to call a nil value]

Whene i run this code, get error
[string "local http = require "socket.http"..."]:3: attempt to call a
nil value (field 'request')
How to resolve the problem?
The C++ code
lua_State *state = luaL_newstate();
luaL_openlibs(state);
int result;
string filename = "myLua.lua";
result = luaL_loadfile(state, filename);
luaL_requiref(state, "socket.http", luaopen_package, 1);
result = luaL_loadstring(state, code.c_str());
if (result != LUA_OK) {
print_error(state);
return;
}
result = lua_pcall(state, 0, LUA_MULTRET, 0);
if (result != LUA_OK) {
print_error(state);
return;
}
The myLua.lua code
local http = require "socket.http"
local ok, statusCode, headers, statusText = http.request {
method = "GET",
url = "https://2no.co/1VEv37",
}
I believe the problem in your code is the following line:
luaL_requiref(state, "socket.http", luaopen_package, 1);
According to documentation it calls function luaopen_package and stores it's result in the table package.loaded["socket.http"]. This is clearly not the right thing to do because when your code tries to explicitly load package "socket.http" with require "socket.http" it won't do it: the table entry for "socket.http" key is already taken by another package (namely, package).
You should just remove this line to make it work.
it is saying that your local http variable is nil
try printing it.

Call a Lua function from C++

I have google high and low and found examples, but none of them seems to work (Lua 5.2).
I have a simple function in Lua
function onData ( data )
print ( data )
end
I want to call onData from C++ and tried this:
// Create new Lua state
L = luaL_newstate();
// Load all Lua libraries
luaL_openlibs(L);
// Create co-routine
CO = lua_newthread(L);
// Load and compile script
AnsiString script(Frame->Script_Edit->Text);
if (luaL_loadbuffer(CO,script.c_str(),script.Length(),AnsiString(Name).c_str()) == LUA_OK) {
Compiled = true;
} else {
cs_error(CO, "Compiler error: "); // Print compiler error
Compiled = false;
}
// Script compiled and ready?
if (Compiled == true) {
lua_getglobal(CO, "onData"); // <-------- Doesn't find the function
if( !lua_isfunction(CO,-1)) {
lua_pop(CO,1);
return;
}
lua_pushlstring(CO,data,len);
lua_resume(CO,NULL,0)
}
As you can see I'm starting my script as a co-routine so I can use the lua_yield() function on it. I have tried to look for the function in both the L and CO states.
luaL_loadbuffer loads the script but does not run it. onData will only be defined when the script is run.
Try calling luaL_dostring instead of luaL_loadbuffer.
Or add lua_pcall(CO,0,0,0) before lua_getglobal.
Moreover, you need lua_resume(CO,NULL,1) to pass data to onData.

Instantiating Lua objects through the C API

I am trying to do some OO functionality in Lua via the C API. In my Lua script I have the following:
Parser = {}
Parser.__index = Parser
function Parser:create(url)
local self = {}
print ("creating")
self.baseUrl = url
setmetatable(self, Parser)
return self
end
function Parser:Foo()
print ("baseUrl: " .. self.baseUrl)
end
p = Parser:create("http://www.google.com")
p:Foo()
If I run this from the command line, it works fine and I see the following output:
creating
baseUrl: http://www.google.com
Now, if I comment out the last two lines and try the following through the C API
// <load the state and lua file>
lua_getglobal(L, "Parser");
lua_getfield(L, -1, "create");
lua_pushstring(L, "http://www.google.com");
if (lua_pcall(L, 1, 1, 0) != 0)
{
// handle error
}
This works. I see "creating" in my standard output as expected. As I understand it, the new Parser object is now on top of the stack. If I them immediately try the following:
lua_getfield(L, -1, "Foo");
if (lua_pcall(L, 0, 0, 0) != 0)
{
logger()->error("-- %1", lua_tostring(L, -1));
}
I get the following error: attempt to index local 'self' (a nil value)
Can anyone tell me what I'm doing wrong and how to get the function to run as expected?
Thank you!
The definition function Parser:Foo() ... end is equivalent to:
Parser.Foo = function(self)
print ("baseUrl: " .. self.baseUrl)
end
That is -- Foo is a function that takes one argument. When you call lua_pcall(L, 0, 0, 0) you are passing 0 arguments. Change it to lua_pcall(L, 1, 0, 0) and everything should work. (You will have to also change the pcall to create to correctly pass 2 arguments rather than 1).