How to print errors in lua script without running script? - c++

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?

Related

Running arbitrary SQL commands MySQL C++ (X DevAPI)?

I've connected my C++ project to MySQL and successfully created a session. I was able to create a Schema. My issue is that when I try to run simple arbitrary queries like USE testSchema SHOW tables; using the MySQL/C++ api, I run into SQL syntax errors. When I run the function directly in the MySQL shell, the query runs perfectly fine.
Here is the full code
const char* url = (argc > 1 ? argv[1] : "mysqlx://pct#127.0.0.1");
cout << "Creating session on " << url << " ..." << endl;
Session sess(url);
{
cout << "Connected!" << endl;
// Create the Schema "testSchema"; This code creates a schema without issue
cout << "Creating Schema..." << endl;
sess.dropSchema("testSchema");
Schema mySchema = sess.createSchema("testSchema");
cout << "Schema Created!" << endl;
// Create the Table "testTable"; This code runs like normal, but the schema doesn't show
cout << "Creating Table with..." << endl;
SqlStatement sqlcomm = sess.sql("USE testSchema SHOW tables;");
sqlcomm.execute();
}
Here is the console output:
Creating session on mysqlx://pct#127.0.0.1 ...
Connected!
Creating Schema...
Schema Created!
Creating Table with...
MYSQL ERROR: CDK Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SHOW tables' at line 1
The error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SHOW tables' at line 1 is a MySQL error that means I have a syntax error in the query, but when I take a closer look at a query, I see there is nothing wrong with it.
I've copied and pasted the code directly from the cpp file into the mysql shell and it runs perfectly. This tells me that something is up with the formatting of how I'm entering the query in the sql() function. But the documentation for the sql() function is really terse and.
Here is the reference to the sql() function: https://dev.mysql.com/doc/dev/connector-cpp/8.0/class_session.html#a2e625b5223acd2a3cbc5c02d653a1426
Can someone please give me some insight on where I'm going wrong? Also here here is the full cpp code for more context:https://pastebin.com/3kQY8THC
Windows 10
Visual Studio 2019
MySQL 8.0 with Connect/C++ X DevAPI
You can do it in two steps:
sess.sql("USE testSchema").execute();
SqlStatement sqlcomm = sess.sql("SHOW tables");
SqlResult res = sqlcomm.execute();
for(auto row : res)
{
std::cout << row.get(0).get<std::string>() << std::endl;
}
Also, you can use the Schema::getTables():
for(auto table : mySchema.getTables())
{
std::cout << table.getName() << std::endl;
}
Keep in mind that the Schema::getTables() doesn't show the Collections created by Schema::createCollection(). There is also a Schema::getCollections():
for(auto collection : mySchema.getCollections())
{
std::cout << collection.getName() << std::endl;
}

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

MySQL call procedure with output parameter from C++ mysqlpp

I need help with the C++ mysqlpp driver calling a stored procedure and retrieving its output parameter. The queries seem to pass successfully but trying to get the stored value causes segmentation fault. My current pseudo code is:
mysqlpp::Connection* connection; // the connection type I am bound to use, no createStatement, prepareStatement methods
Query query = connection->query();
Query transactionQuery = connection->query();
query << "CALL sp_get_transactions_count(" << inputId << ", #transactionsCount);";
transactionQuery << "SELECT #transactionsCount as combinations;";
ClearQuerySentry cleanUpQuery(transactionQuery);
query.exec();
mysqlpp::StoreQueryResult transactionsResult = transactionQuery.store();
if (!transactionsResult || transactionsResult.num_rows() == 0)
{
logWarning(....);
}
else
{
const mysqlpp::Row& transactionRecord = result[0];
environment.pairTransactionsCount = verboseLexicalCast<int>(transactionRecord, "combinations"); // segfault on trying to cast static_cast<const char*>(row[fieldName.c_str()]))
}
I am not very experienced with mysqlpp and MySQL as a whole so it is possible my perception of the solution to be wrong. Thanks in advance.

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.