Get table from c++ lua reference index in lua - c++

first sorry for the weired title :(
I am using lua as a scripting languge for my game and I have a problem:
I am creating lua table instances and storing them in indices "ref_idx " like this:
lua_newtable(L);
lua_getglobal(L, "TestTable"); // create instance of table "TestTable"
lua_pcall(L, 0, 1, 0);
ref_idx = luaL_ref(L, LUA_REGISTRYINDEX);
and when i want to call a method of one of them I use :
lua_rawgeti(L, LUA_REGISTRYINDEX, ref_idx);
lua_getfield(L, -1, "testMethod");
lua_pushvalue(L, -2);
lua_pcall(L, 1, 0, 0));
lua_pop(L, 0);
when I am done with the reference :
luaL_unref(L, LUA_REGISTRYINDEX, ref_idx);
Every thing works fine, the problem is I want to use these reference in lua directly something like :
function onUpdate()
local ref = GetReferenceFromC++() -- returns ref_idx
ref:testMethod()
end
Any help or a way to do it?
(sorry for my english, I am working on it)

I used debug.getregistry()[ref]:testMethod()
and it works, Thank you #EgorSkriptunoff for your quick response.

Related

Adding searcher in package.searchers with lua c api?

Issue
I want require in lua to be able to find module in a game assets archive using Physfs.
After some searche, i must add a c function to the package.searchers table ?
I tried to do so, but sadly i can't manage to. I'm new to lua and embeding lua, so it is definitly not helping.
One thing i don't get is, the package table and all the nested table in there are not global? I tried to add a lua function to the table (so lua side of things) and i get nothing because package is nil.
With something like this:
package.searchers[#package.searchers + 1] = function(name)
print("searchers as been called.")
end
Edit
For the package library (and the other one), here is how i basically load it :
const luaL_Reg lualibs[] = {
{ LUA_COLIBNAME, luaopen_base },
{ LUA_LOADLIBNAME, luaopen_package },
{ LUA_TABLIBNAME, luaopen_table },
{ LUA_IOLIBNAME, luaopen_io },
{ LUA_OSLIBNAME, luaopen_os },
{ LUA_STRLIBNAME, luaopen_string },
{ LUA_MATHLIBNAME, luaopen_math },
{ LUA_DBLIBNAME, luaopen_debug },
{ NULL, NULL }
};
lua_State* ls = luaL_newstate();
const luaL_Reg* lib = lualibs;
for (; lib->func; lib++) {
lua_pushcfunction(ls, lib->func);
lua_pushstring(ls, lib->name);
lua_call(ls, 1, 0);
}
Edit 2
Problem solved, thanks to Egor Skriptunoff's answere.
All i have to do was loading the libraries with luaL_openlibs directly. then i can do something like that :
lua_getglobal(_ls, LUA_LOADLIBNAME);
if (!lua_istable(_ls, -1))
return;
lua_getfield(_ls, -1, "searchers");
if (!lua_istable(_ls, -1))
return;
lua_pushvalue(_ls, -2);
lua_pushcclosure(_ls, mysearcher, 1);
lua_rawseti(_ls, -2, 5);
lua_setfield(_ls, -2, "searchers");
Some info
I use LUA 5.4
It's a c++ project.
I guess i have to post and answere to mark this post as solved.
First things, package table was not global because i was loading libraries wrong. i need to use luaL_requiref as mentioned by Egor Skriptunoff or directly luaL_openlibs.
Then after that, because it is now global, i can just do something like that for exemple :
lua_getglobal(_ls, LUA_LOADLIBNAME);
if (!lua_istable(_ls, -1))
return;
lua_getfield(_ls, -1, "searchers");
if (!lua_istable(_ls, -1))
return;
lua_pushvalue(_ls, -2);
lua_pushcclosure(_ls, mysearcher, 1);
lua_rawseti(_ls, -2, 5);
lua_setfield(_ls, -2, "searchers");

lua return string c++

There is a function on Lua:
STRING getClassesList()
It returns string as it is to get on c++:
This does not work:
Const char * ClassesStr;
Lua_getglobal (L, "getClassesList");
Lua_pcall (L, 1, 1, 0);
ClassesStr = lua_tostring (L, 1);
stack: 'readQuikAgent' 'attempt to call a table value'
The function is designed to obtain a list of class codes sent from the server during the communication session. The class codes in the list are separated by a comma ",". At the end of the received line, the symbol "," is always appended.
Call format:
STRING getClassesList ()
Example:
List = getClassesList ()
As a result of the above line of code, the list variable contains a string of the form:
OPTEXP, USDRUB, PSOPT, PSFUT, SPBFUT
'attempt to call table value' means that the item at the top of the lua stack is a table not a function.
So the result of the getglobal was a table, and that can not be called.
It works (thank you siffiejoe):
lua_pcall(L, 0, 1, 0);
ClassesStr = lua_tostring(L, -1);

C++ SQLite3 prepared delete statement not working

I have a C++ application which loops through a SQLite3 database. Each row contains an ID which is checked against a vector. If the ID in the DB is not present in the vector, it should be deleted with a prepared statement. I use the following code, however the ID's won't get deleted. I Neither can get an error message from the sqlite3_step(stmt2) function.
//SETTINGS["Reference"] CONTAINS THE REFERENCE FOR THE ID's (IT's 1 FOR UNDERNEATH EXAMPLE)
vector<int> IDs; //THIS VECTOR CONTAINS THE ID's IN MY APPLICATION
rc = sqlite3_prepare_v2(db, "SELECT ID FROM Files WHERE Reference=?", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, Settings["Reference"].c_str(), Settings["Reference"].length(), 0);
CheckDBError(rc);
rc = sqlite3_step(stmt);
sqlite3_stmt* stmt2;
int rc2 = sqlite3_prepare_v2(db, "DELETE FROM Files WHERE ID=? AND Reference=?", -1, &stmt2, 0);
CheckDBError(rc2);
while(rc == SQLITE_ROW) {
string IDToCheck = NumberToString(sqlite3_column_int64(stmt, 0));
if (std::find(IDs.begin(), IDs.end(), IDToCheck) == IDs.end()) { //VERIFY AGAINST VECTOR WORKS AS EXPECTED
//I GET HERE WITH ALL MY ID's I HAVE CHECKED THAT ALREADY :)
sqlite3_bind_text(stmt2, 1, IDToCheck.c_str(), IDToCheck.length(), 0);
sqlite3_bind_text(stmt2, 2, Settings["Reference"].c_str(), Settings["Reference"].length(), 0);
rc2 = sqlite3_step(stmt2);
//CAN'T GET ANY ERROR MESSAGE (SO QUERY IS FINE, WHICH SEEMS LIKE IT?)
}
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
sqlite3_finalize(stmt2);
You must not call the finalize function before the while block, because that way you finalize your statement before using it. As per SQLite documentation (emphasis mine):
It is a grievous error for the application to try to use a prepared
statement after it has been finalized. Any use of a prepared statement
after it has been finalized can result in undefined and undesirable
behavior such as segfaults and heap corruption.

Using sqlite3_bind_XXX inside a loop

I want to do multiple parameterized inserts with SQLite in my code. For this :
I have a single prepare statement outside of my loop as :
error = sqlite3_prepare(connection, insert_sql, strlen(insert_sql), &stmt, NULL);
I want inserts within a loop as:
while ( not reached end of datafile ) {
// Insert into server table
sqlite3_bind_int(stmt, 1, id1);
sqlite3_bind_double(stmt, 2, latitude);
sqlite3_bind_double(stmt, 3, longitude);
sqlite3_step(stmt);
}
The API docs for the function : https://www.sqlite.org/c3ref/bind_blob.html
mention that :
sqlite3_step() has been called more recently than sqlite3_reset(), then the call will return SQLITE_MISUSE
Bindings are not cleared by the sqlite3_reset() routine
If any sqlite3_bind_() routine is passed a prepared statement that has
been finalized, the result is undefined and probably harmful.
I am really confused as to how do I do repeated inserts with parameterized query in SQLite?
Just call sqlite3_reset() after sqlite3_step().

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