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

Reply via email to