gpt4 book ai didi

lua - 如何实现表到函数的跟踪功能?

转载 作者:行者123 更新时间:2023-12-02 13:34:29 25 4
gpt4 key购买 nike

我有一张这样的 table

local ftable = {
getPinId = app.getPinId
}

ftable 被传递给另一个函数,该函数将其导出为 RPC 接口(interface)。这可行,但现在我想将函数调用跟踪添加到日志文件中。

简单的方法是

local ftable = {
getPinId = function(...) print("getPinId") app.getPinId(...) end
}

但是,这并不是特别好。我想写一些类似的内容:

local trace = function(func, ...)
return function(...) print(func) func(...) end
end

local ftable = {
getPinId = trace(app.getPinId)
}

但这并没有产生完全期望的结果。参数没有被传递。

另一种选择是使用像这样的元表:

local ftable = {}
setmetatable(ftable, {
__index = function(_, k)
printf("Call: app.%s\n", k) return app[k] end
})

这有效。但如果可能的话,我还希望能够打印传递的参数。

有什么建议吗?如果这有什么区别的话,我只使用 luajit。

最佳答案

在 Lua 中包装函数调用很容易:

local function wrap( f )
local function after( ... )
-- code to execute *after* function call to f
print( "return values:", ... )
return ...
end
return function( ... )
-- code to execute *before* function call to f
print( "arguments:", ... )
return after( f( ... ) )
end
end


local function f( a, b, c )
return a+b, c-a
end

local f_wrapped = wrap( f )
f_wrapped( 1, 2, 3 )

输出是:

arguments:  1   2   3
return values: 3 2

日志记录/跟踪的一个问题是 Lua 值(包括函数)本身没有名称。调试库尝试通过检查函数的调用方式或存储位置来为函数找到合适的名称,但如果您想确定,则必须自己提供一个名称。但是,如果您的函数存储在(嵌套)表中(如注释中所示),您可以编写一个迭代嵌套表的函数,并使用表键作为名称包装它找到的所有函数:

local function trace( name, value )
local t = type( value )
if t == "function" then -- do the wrapping
local function after( ... )
print( name.." returns:", ... )
return ...
end
return function( ... )
print( "calling "..name..":", ... )
return after( value( ... ) )
end
elseif t == "table" then -- recurse into subtables
local copy = nil
for k,v in pairs( value ) do
local nv = trace( name.."."..tostring( k ), v )
if nv ~= v then
copy = copy or setmetatable( {}, { __index = value } )
copy[ k ] = nv
end
end
return copy or value
else -- other values are ignored (returned as is)
return value
end
end


local ftable = {
getPinId = function( ... ) return "x", ... end,
nested = {
getPinId = function( ... ) return "y", ... end
}
}

local ftableTraced = trace( "ftable", ftable )
ftableTraced.getPinId( 1, 2, 3 )
ftableTraced.nested.getPinId( 2, 3, 4 )

输出是:

calling ftable.getPinId:    1   2   3
ftable.getPinId returns: x 1 2 3
calling ftable.nested.getPinId: 2 3 4
ftable.nested.getPinId returns: y 2 3 4

需要注意的一些事项:

  1. 表键可以是任意 Lua 值,而不仅仅是完全由可打印字符组成的短字符串。
  2. 表可以包含循环引用。如果这样做,上面的简单实现将会因堆栈溢出而终止。

关于lua - 如何实现表到函数的跟踪功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37871685/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com