How do I invoke a class method using pcall in Lua?
I tried pcall(instance:method, arg) but it doesn't work.
I also tried pcall(instance.method, instance, arg) but that doesn't work either.
I googled for a solution but I couldn't get one.
An example:
local ValueOwnerMap = {}
ValueOwnerMap.__index = ValueOwnerMap
function ValueOwnerMap:create(key_prefix)
local instance = {}
setmetatable(instance, ValueOwnerMap)
instance.key = key_prefix .. ':value-owner-map'
return instance
end
function ValueOwnerMap:get(value)
return redis.call('HGET', self.key, value)
end
function ValueOwnerMap:put(value, owner_id)
return redis.call('HSETNX', self.key, value, owner_id)
end
function ValueOwnerMap:del(value)
return redis.call('HDEL', self.key, value)
end
local value_owner_map = ValueOwnerMap:create('owner:key')
local success, data = pcall(value_owner_map:put, 'a_value', 'a_owner_id')
instance:method(arg) is sugar for instance.method(instance,arg). So try
pcall(value_owner_map.put, value_owner_map, 'a_value', 'a_owner_id')
The following line replaces the last line of the block in the question. It works.
local success, data = pcall(function () value_owner_map:put('a_value', 'a_owner_id') end)
Thank you all for sharing
pcall (f, arg1, ยทยทยท)
Calls function f with the given arguments in protected mode. This means that any error inside f is not propagated; instead, pcall catches the error and returns a status code. lua ref
But Calls for functions in protected mode have some limitations especially when you are using ':' operator 'so-called synthetic sugar' of lua.
one way to WAR this limitation is to put inside a function
pcall(function () value_owner_map:put('a_value', 'a_owner_id') end)
This approach also catches the errors as usual:
local ok, msg = pcall(function () error('Phony Error') end)
if ok then
print("No error")
else
print("Got error".. tostring(msg))
end
-- Result:
-- Got error test.lua:53: Phony Error
Related
What I want to avoid is to capture/ignore the exception when FFI calls a non-existent method.
For example, the following code calls the non_existent_method. However, pcall cannot handle the error.
local ffi = require "ffi"
local C = ffi.C
ffi.cdef [[
int non_existent_method(int num);
]]
local ok, ret = pcall(C.non_existent_method, 1)
if not ok then
return
end
I got the following error with OpenResty/lua-nginx-module.
lua entry thread aborted: runtime error: dlsym(RTLD_DEFAULT, awd): symbol not found
One more apporach would be to call the index metamethod directly:
You might want to wrap that into a function:
local ffi_mt = getmetatable(ffi.C)
function is_valid_ffi_call(sym)
return pcall(ffi_mt.__index, ffi.C, sym)
end
example:
ffi.cdef[[void (*foo)();]]
ffi.cdef[[int puts(const char *);]]
a,func = is_valid_ffi_call("foo")
-- false, "error message: symbol not found or missing declaration, whatever it is"
a,func = is_valid_ffi_call("puts")
-- true, cdata<int ()>: 0x7ff93ad307f0
One possible solution would be wrapping the C.non_existent_method call with a lua function.
For example
local ok, ret = pcall(function()
return C.non_existent_method(len)
end)
if not ok then
......
end
In the below code, can anyone explain why does t1:print() works but (t1):print fails. I am attempting to make something like (t1 * 3):print() work without using an intermediate variable.
function classTestTable(members)
members = members or {}
local mt = {
__metatable = members;
__index = members;
}
function mt.print(self)
print("something")
end
return mt
end
TestTable = {}
TestTable_mt = ClassTestTable(TestTable)
function TestTable:new()
return setmetatable({targ1 = 1}, TestTable_mt )
end
TestTable t1 = TestTable:new()
t1:print() -- works fine.
(t1):print() -- fails with error "attempt to call a boolean value"
Lua expressions can extend over multiple lines.
print
(3)
Will print 3
So
t1:print()
(t1):print()
actually is equivalent to
t1:print()(t1):print()
or
local a = t1:print()
local b = a(t1)
b:print()
So you're calling the return value of t1:print()
To avoid that follow Egors advice and separate both statements with a semicolon.
t1:print();(t1):print()
i have code in my lua file and i edit that to look like this
function getUserinfo(user_id)
function call_back_user_info(status , result)
t = {["first_name"]= result.first_name_, ['have_access']= result.have_access_, ["last_name"]=result.last_name_,["user_name"]=result.username_}
return t
end
getUser(user_id,call_back_user_info)
end
i need to return t table value when i call getUserinfo function.but it is get me a nil value !
note :getUser function puts data in to call_back_user_info
how i can resolve this problem? thank
You can't do a "long return" which returns from an outer function from inside of an inner function.
But what you can do is create a local variable which is closed over, like this:
function getUserinfo(user_id)
local t
function call_back_user_info(status , result)
t = {["first_name"]= result.first_name_,
['have_access']= result.have_access_,
["last_name"]=result.last_name_,
["user_name"]=result.username_}
end
getUser(user_id,call_back_user_info)
return t
end
I have the following problem, somebody can help me?
comp = {}
comp.__index = function(obj,val)
if val == "insert" then
return rawget(obj,"gr")["insert"]
end
return rawget(obj, val)
end
comp.new = function()
local ret = {}
setmetatable(ret, comp)
ret.gr = display.newGroup()
return ret
end
local pru = comp.new()
pru.gr:insert(display.newImage("wakatuBlue.png"))
This line works, but I don't want to access the insert method using the gr property, I want to call the insert method directly and the metatable __index function does the work
pru:insert(display.newImage("wakatuBlue.png"))
This line doesn't work and I get this error: "bad argument #-2 to 'insert' (Proxy expected, got nil)", but this is the way that I'm looking to use
Do you want something like this?
comp = {}
comp.__index = function(obj,val)
if val == "insert" then
return rawget(obj,"gr"):insert(val)
end
return rawget(obj, val)
end
__index works just fine; it's because your last call is interpreted as:
pru.insert(pru, display.newImage("wakatuBlue.png"))
whereas you want/need it to be:
pru.insert(pru.gr, display.newImage("wakatuBlue.png"))
You either need to call it like this or explain what you are trying to do.
_ENV currently hates using classes. I'm attempting to create a Latin kind of Lua, and some things can't precisely be made with _ENV but it's a lot more efficient. setfenv was being uncooperative as well.
The subsequent code keeps returning the old attempt to call a nil value error. It specifies line 20, in which loadstring() is being checked, and line 23, where in the main chunk it is calling the __latin() function.
function __latin(code)
__predecessor = [===[
function typographia(value)
print(value);
end
chorda = {};
chorda.__index = chorda;
function chorda.sub(chorda, cChorda, fChorda)
return string.sub(chorda, cChorda, fChorda);
end
function chorda:sub(chorda, cChorda, fChorda)
return string.sub(chorda, cChorda, fChorda);
end
--[[ define values --]]
_ENV = {salve="Salve, munde!",typographia=typographia,print=print,chorda=chorda,chorda.sub=chorda.sub}; ]===];
__finalizer = __predecessor .. " " .. code;
local status, err = pcall(loadstring(__finalizer));
print(err);
if (err == nil) then loadstring(__finalizer)(); end
end
__latin('typographia(salve); chorda.sub(salve, 1, 3);');
You're getting "attempt to call a nil value" because loadstring returns nil (so you're calling pcall with nil). loadstring returns nil because the code you're compiling (__predecessor) contains invalid Lua:
_ENV = {
chorda.sub = chorda.sub -- can't do this
}
FYI: The loadstring/pcall stuff is irrelevant to your problem. Had you stripped it out before posting, you would have found this error yourself.