In my C++ app, I have a string which contains XML data. Let's say I have an attribute Number1 and an attribute Number2.
I want to send that string to a Lua script and have it return a modified XML string. Let's say it adds a new attribute Product with the value of Number1 and Number2.
Is that easily done using C++/Lua, and if so how?
There are several methods to work with XML data listed at the Lua Users Wiki. The better options involve calls back to C (e.g. LuaXML and LuaExpat) so this only makes sense to do if there are other reasons to use Lua beyond just parsing XML.
Not a Lua user myself...but just browsing the documentation, it seems that you can use lua_pushstring() to put a copy of a null-terminated C string into the Lua stack:
http://pgl.yoyo.org/luai/i/lua_pushstring
Although there is no specific definition for things like lua_popstring() you can define something like that yourself:
std::string lua_popstring(lua_State *L)
{
std::string tmp = lua_tostring(L, lua_gettop(L));
lua_pop(L, 1);
return tmp;
}
With that in hand you should be able to modify the standard example for passing data into Lua and getting a result back for your purpose:
http://lua-users.org/wiki/SimpleLuaApiExample
You could do it similar to this (not this might not be 100 % correct due to being out of my mind and it doesn't include error handling):
lua_getglobal(L, "modifyXml"); // push function on stack by name
lua_pushstring(L, xml); // push the xml string as parameter
lua_pcall(L, 1, 1, 0); // call the function with 1 parameter, 1 return value and no error handler
strcpy(xml, lua_tostring(L, -1)); // get the top of the stack as a string and copy it to xml
lua_pop(xml, 1); // remove the string from the stack
The lua function called could look like this:
function modifyXml(xml)
-- do something with xml here
return xml
end
If you use Luabind it could look something like this in C++:
std::string result = luabind::call_function<std::string>(
"yourLuaFunction", inputXmlString);
You would implement yourLuaFunction in Lua of course, and require that Lua module from within your C++ program.
Related
I have a Lua thread running, and a Qt-powered text edit running in parallel. I want the user to be able to run any Lua code he has written in the text edit, but it doesn't work well. It works with simple instruction(s), like "print(5)" or "tmp = 5; print(tmp)" but it doesn't work with strings (print( "hello world") ) or numeric expressions like print(5+3).
And, worst of all, it doesn't work if I try to call a lua function defined before or a C registered function.
If I delete signals&slots etc, my code is roughly this :
const char* text = textEdit->toPlainText().toLatin1().data();
luaL_loadstring(_LuaState, text);
lua_pcall(_LuaState, 0, LUA_MULTRET, 0); ///These 2 lines used to be luaL_doString,
// but it didn't work
the Lua State is the same that the one where I registered C functions and loaded a lua file defining some others functions
I'm using SQLite (3.6.4) from a C++ application (using the standard C api). My question is: once a query has been prepared, using sqlite3_prepare_v2(), and bound with parameters using sqlite3_bind_xyz() - is there any way to get a string containing the original SQL query?
The reason is when something goes wrong, I'd like to print the query (for debugging - this is an in-house developer only test app).
Example:
sqlite3_prepare_v2(db, "SELECT * FROM xyz WHERE something = ? AND somethingelse = ?", -1, &myQuery, NULL);
sqlite3_bind_text(myQuery, 1, mySomething);
sqlite3_bind_text(myQuery, 2, mySomethingElse);
// ....
// somewhere else, in another function perhaps
if (sqlite3_step(myQuery) != SQLITE_OK)
{
// Here i'd like to print the actual query that failed - but I
// only have the myQuery variable
exit(-1);
}
Bonus points if it could also print out the actual parameters that was bound. :)
You probably want to use sqlite3_trace
This will call a callback function (that you define) and on of the parameters is a char * of the SQL of the prepared statements (including bound parameters).
As per the comments in sqlite3.c (amalgamation), sqlite3_sql(myQuery) will return the original SQL text.
I don't see any function for finding the value bound at a particular index, but we can easily add one to the standard set of SQLite functions. It may look something like this:
const char* sqlite3_bound_value(sqlite3_stmt* pStmt, int index)
{
Vdbe *p = (Vdbe *)pStmt;
// check if &p->aVar[index - 1] points to a valid location.
return (char*)sqlite3ValueText(&p->aVar[index - 1], SQLITE_UTF8);
}
Well, the above code shows only a possible way sqlite3_bound_value() could be implemented. I haven't tested it, it might be wrong, but it gives certain hints on how/where to start.
Quoting the documentation:
In the "v2" interfaces, the prepared statement that is returned (the sqlite_stmt object) contains a copy of the original SQL text.
http://www.sqlite.org/c3ref/prepare.html
How can I make a lua table in C++ map to a lua script where the script defines the table properties and methods, so the resulting lua file looks something like:
Script.test = 5
function Script:Update()
end
So this script could be read in many times but each time it should get its own unique table in C++.
The idea is that from C++ I want to call each unique Update() method and be able to read/set its test variable.
Let's say you are making a video game and I told you if you make scripts structured like this and attach them to models that the game will run the Update() method every frame and that the variables you define are local to that script/model.
This answer is just to elaborate on my comment above. One simple idea to achieve what you're describing is to just create that local table right in the script file and return that table at the end.
local Script = {}
Script.test = 5
Script.foo = "bar"
function Script:Update()
end
return Script
This is the usual approach taken to put lua modules into its own namespace and to avoid global scope pollution.
You can grab and use the returned Script table off the stack with something like this:
// load and execute your script
luaL_dofile(L, "script.lua");
// Run Script:Update()
lua_getfield(L, -1, "Update");
lua_pushvalue(L, -2);
lua_call(L, 1, 0);
You can wrap the above code snippet into a function to make it easier to call as many times as desired. You can even make it more efficient by caching the compiled script.lua somewhere to avoid reparsing and recreating the wrapping function everytime this function is called. For example:
lua_getfield(L, LUA_REGISTRYINDEX, "cached_script");
if (lua_isnil(L, -1))
{
luaL_loadfile(L, "script.lua");
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, "cached_script");
}
lua_pcall(L, 0, 0, 0);
// etc.
Good day
I have a specific task to give an access of c++ std::map to lua scripts. Desired script syntax is glob["tag"] = "value" or glob("tag") = "value"
In research, have tried luabind binding
std::string & glob(const std::string &tag)
{
static std::string value;
return value;
}
...
luabind::module(&state)
[
def("glob", &glob, luabind::return_reference_to(result))
]
but after run of script listed below
glob("tag") = "asdasd"
print(glob("tag"))
got error [string "glob("tag") = "asdasd"..."]:1: unexpected symbol near '='
So, i'm waiting for your suggestions and opinions.
Thanks
Update
2lhf: Global variables data stored and serialized via c++ part and has to be accessed from lua.
luaState is created per script execution, and doesn't exist between executions. One of solution is create and fill global variables table before script execution and sync it with map after execution, but, i think it is slow enough. So, access via c-function with mentioned syntax will be appreciated.
glob("tag") = "asdasd" can never work, because it's not valid Lua syntax. glob["tag"] = "value" can work. You need to set glob as a userdata with index and newindex metamethods. I don't know anything about luabind, so I cannot help you there. But doing it using the standard Lua API is not hard. I just wonder why you need to export C++ map to Lua, when Lua has excellent associative arrays already.
Yep, metatable rules.
Just had to insert some c code get from samples
lua_createtable(&state, 0, 0);
lua_pushcfunction(&state, &getValue);
lua_setfield(&state, -2, "__index");
lua_pushcfunction(&state, &setValue);
lua_setfield(&state, -2, "__newindex");
lua_setmetatable(&state, -2);
lua_setglobal(&state, "global");
And everything works just fine, thanks
But here is another question: why i should use index == -2 for lua_setfield and lua_setmetatable?
I'm using SQLite (3.6.4) from a C++ application (using the standard C api). My question is: once a query has been prepared, using sqlite3_prepare_v2(), and bound with parameters using sqlite3_bind_xyz() - is there any way to get a string containing the original SQL query?
The reason is when something goes wrong, I'd like to print the query (for debugging - this is an in-house developer only test app).
Example:
sqlite3_prepare_v2(db, "SELECT * FROM xyz WHERE something = ? AND somethingelse = ?", -1, &myQuery, NULL);
sqlite3_bind_text(myQuery, 1, mySomething);
sqlite3_bind_text(myQuery, 2, mySomethingElse);
// ....
// somewhere else, in another function perhaps
if (sqlite3_step(myQuery) != SQLITE_OK)
{
// Here i'd like to print the actual query that failed - but I
// only have the myQuery variable
exit(-1);
}
Bonus points if it could also print out the actual parameters that was bound. :)
You probably want to use sqlite3_trace
This will call a callback function (that you define) and on of the parameters is a char * of the SQL of the prepared statements (including bound parameters).
As per the comments in sqlite3.c (amalgamation), sqlite3_sql(myQuery) will return the original SQL text.
I don't see any function for finding the value bound at a particular index, but we can easily add one to the standard set of SQLite functions. It may look something like this:
const char* sqlite3_bound_value(sqlite3_stmt* pStmt, int index)
{
Vdbe *p = (Vdbe *)pStmt;
// check if &p->aVar[index - 1] points to a valid location.
return (char*)sqlite3ValueText(&p->aVar[index - 1], SQLITE_UTF8);
}
Well, the above code shows only a possible way sqlite3_bound_value() could be implemented. I haven't tested it, it might be wrong, but it gives certain hints on how/where to start.
Quoting the documentation:
In the "v2" interfaces, the prepared statement that is returned (the sqlite_stmt object) contains a copy of the original SQL text.
http://www.sqlite.org/c3ref/prepare.html