LuaBridge Indescriptive errors - c++

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.

Related

Saving the output from Lua in C++ with SOL3 to an std::string

I'm trying to implement a lua interpreter to my C++ code. I have implemented a small editor for my project using ImGui and I'm saving the output from the editor to an std::vector.
My attempted implementation of my lua interpeter looks like so;
// header
std::string ExecuteLua();
std::vector<char> m_luaEditorData;
// cpp
std::string Proxy::ExecuteLua()
{
// Load the Lua code from the string
std::string luaCode(m_luaEditorData.data());
// Create a Lua state
sol::state lua;
// Load standard Lua libraries
lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::string, sol::lib::table);
// Execute the Lua code and store the result
sol::protected_function_result result = lua.script(luaCode);
// Check for errors
if (!result.valid())
{
sol::error error = result;
std::string errorMsg = error.what();
return "Lua error: " + errorMsg;
}
// Get the result as a string
std::string output = lua["tostring"](result.get<sol::object>());
// Return the output
return output;
}
...
if (m_luaEditorData.empty())
m_luaEditorData.push_back('\0');
auto luaEditorFlags = ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_CallbackResize;
ImGui::InputTextMultiline("##LuaEditor", m_luaEditorData.data(), m_luaEditorData.size(), ImVec2(ImGui::GetWindowContentRegionWidth(), ImGui::GetWindowHeight() - (ImGui::GetTextLineHeight() * 16)), luaEditorFlags, ResizeInputTextCallback, &m_luaEditorData);
...
When I run this code, I only get nil in my output, the correct output to stdout (don't really want it to output here, but to my std::string and when I put in bad code, it throws an exception in sol.hpp. I didn't really find any examples on how I can do this and I'm therefore am trying to figure this out on my own.

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?

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.

lua function argument expected near <eof>

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.

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).