function gettable_event (table, key)
local h
if type(table) == "table" then
local v = rawget(table, key)
if v ~= nil then return v end
h = metatable(table).__index
if h == nil then return nil end
else
h = metatable(table).__index
if h == nil then
error(···)
end
end
if type(h) == "function" then
return (h(table, key)) -- call the handler
else return h[key] -- or repeat operation on it
end
end
local father = {}
local child = {}
setmetatable(child, child)
child.__index = father
local father = {}
local child = {}
setmetatable(child, {__index = father})
-- tostring方法
function class.object:__tostring()
if self then
local ret = '[' .. self.__type .. ' : ' .. self.__classname .. ']'
if self.__instance_id then
ret = ret .. ' @' .. tostring(self.__instance_id)
end
return ret
end
return '[class : object] WARNING: you should use obj:__tostring but obj.__tostring'
end
-- 单例基类
do
class.singleton = class.register('utils.class.singleton')
rawset(class.singleton, 'new', function(self, inst)
if nil == self then
log_error('singleton class must using class:new or class:instance(class.new and class.instance is unavailable)')
return nil
end
return self
end)
rawset(class.singleton, 'instance', class.singleton.new)
end
-- 保护table数据
function class.protect(obj, r)
-- 和readonly混用的优化
local tmb = getmetatable(obj)
if tmb and class.readonly__newindex == tmb.__newindex then
obj = tmb.__index
end
local wrapper = {}
local wrapper_metatable = {}
setmetatable(wrapper, wrapper_metatable)
for k, v in pairs(obj) do
if r and 'table' == type(v) or 'userdata' == type(v) then
rawset(wrapper, k, class.protect(v, r))
else
rawset(wrapper, k, v)
end
end
rawset(wrapper_metatable, '__index', obj)
rawset(wrapper_metatable, '__newindex', function(tb, k, v)
rawset(tb, k, v)
end)
return wrapper
end
-- readonly 重载__newindex函数
function class.readonly__newindex(tb, key, value)
log_error('table %s is readonly, set key %s is invalid', tostring(tb), tostring(key))
end
-- 设置table为readonly
function class.set_readonly(obj)
local tmb = getmetatable(obj)
if not tmb or class.readonly__newindex ~= tmb.__newindex then
local wrapper = {
__index = obj,
__newindex = class.readonly__newindex,
}
-- 设置readonly后 # 操作符失效的解决方案
function wrapper:table_len()
return #obj
end
-- 设置readonly后pairs失效的解决方案
function wrapper:table_pairs()
return pairs(obj)
end
-- 设置readonly后ipairs失效的解决方案
function wrapper:table_ipairs()
return ipairs(obj)
end
-- 设置readonly后next失效的解决方案
function wrapper:table_next(index)
return next(obj, index)
end
-- 设置readonly后unpack失效的解决方案
function wrapper:table_unpack(index)
return table.unpack(obj, index)
end
-- 原始table
function wrapper:table_raw()
return obj
end
-- 复制可写表
function wrapper:table_make_writable()
local ret = table.extend(obj)
for k, v in pairs(ret) do
if 'table' == type(v) then
rawset(ret, k, v:table_make_writable())
else
rawset(ret, k, v)
end
end
return ret
end
setmetatable(wrapper, wrapper)
for k, v in pairs(obj) do
if 'table' == type(v) or 'userdata' == type(v) then
rawset(obj, k, class.set_readonly(v))
end
end
return wrapper
end
return obj
end
local ut = unit.new(unit_id) -- 这里这个对象引用计数为1,在缓存池里。如果没有缓存池,引用计数为0,就会被销毁
-- ut 只有一次弱引用,不会影响实际的对象回收
/**
* 给类添加方法,自动推断类型
*
* @tparam TF Type of the tf.
* @param func_name Name of the function.
* @param fn The function.
*/
template<typename R, typename... TParam>
self_type& addMethod(const char* func_name, R(*fn)(TParam... param)) {
lua_State* state = getLuaState();
lua_pushstring(state, func_name);
lua_pushlightuserdata(state, reinterpret_cast<void*>(fn));
lua_pushcclosure(state, detail::unwraper_static_fn<R, TParam...>::LuaCFunction, 1);
lua_settable(state, getStaticClassTable());
return (*this);
}