Hello.
I'm newbie in Lua and tries to expose several objects' methods to ubus. In
current implementation only function is allowed as methods, but I need to pass
objects to such functions. Here is the snippet:
============
local uci = require "uci"
local ubus = require "ubus"
local uloop = require "uloop"
local x = uci.cursor()
uloop.init()
local conn = ubus.connect()
if not conn then
error("Failed to connect to ubus")
end
local SDRs = { }
for s,e in pairs(x:get_all('SDR')) do
print('-------- '..s..' --------')
local t = e['.type']
local klass = require ("sdr."..t)
local obj = klass:new(e, true)
SDRs['SDR.'..e['.name']] = obj:ubus_methods(conn)
end
conn:add(SDRs)
uloop.run()
=================
The klass method ubus_methods returns:
=================
function _M.ubus_methods(self, conn)
local _g = setmetatable({_o = self, _conn = conn}, {
__call = function(tbl, req, msg)
tbl._conn:reply(req, { rpm = tbl._o:get() })
end})
local _s = setmetatable({_o = self, _conn = conn}, {
__call = function(tbl, req, msg)
tbl._conn:reply(req, { status = tbl._o:set(tonumber(msg['duty'])) })
end})
local _f = setmetatable({_o = self, _conn = conn}, {
__call = function(tbl, req, msg)
tbl._conn:reply(req, { status=tbl._o:fanmap() })
end})
return {
get = { _g, { } },
set = { _s, { duty = ubus.INT32 } },
fanmap = { _f, { } }
}
end
=================
So, I wrote a little patch to add additional check for "__call" metamethod to
make it possible.
BTW. There is no code to check signatures (policy) of methods for Lua code.
--
Anton D. Kachalov
--- ubus/lua/ubus.c.orig 2016-05-24 20:00:49.000000000 +0300
+++ ubus/lua/ubus.c 2016-06-16 17:22:31.986092619 +0300
@@ -293,7 +293,7 @@ ubus_method_handler(struct ubus_context
lua_remove(state, -2);
lua_remove(state, -2);
- if (lua_isfunction(state, -1)) {
+ if (lua_isfunction(state, -1) || lua_istable(state, -1)) {
lua_pushlightuserdata(state, req);
if (!msg)
lua_pushnil(state);
@@ -359,13 +359,29 @@ static int ubus_lua_load_methods(lua_Sta
lua_gettable(L, -3);
/* check if the method table is valid */
- if ((lua_type(L, -2) != LUA_TFUNCTION) ||
+ if (((lua_type(L, -2) != LUA_TFUNCTION) && (lua_type(L, -2) != LUA_TTABLE)) ||
(lua_type(L, -1) != LUA_TTABLE) ||
lua_objlen(L, -1)) {
lua_pop(L, 2);
return 1;
}
+ if (lua_type(L, -2) == LUA_TTABLE) {
+ /* check for metatable */
+ if (lua_getmetatable(L, -2) == 0) {
+ lua_pop(L, 2);
+ return 1;
+ }
+ lua_pushstring(L, "__call");
+ lua_rawget(L, -2);
+ lua_replace(L, -2);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 6);
+ return 1;
+ }
+ lua_pop(L, 1);
+ }
+
/* store function pointer */
lua_pushvalue(L, -2);
lua_setfield(L, -6, lua_tostring(L, -5));
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel