Instantiating Lua objects through the C API - c++

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

Related

Get table from c++ lua reference index in lua

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.

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.

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

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.