我为我的项目实现了计时器(对于 lua 5.1,完整的源代码、dll 和测试可在http://wintarif.narod.ru/products.htm获得,所以我将跳过有问题的完整源代码)。Timer 创建对象并实现 CreateTimerQueueTimer。我做了 3 个不同行为的测试:共享部分测试脚本
require('timer')
-- params same as CreateTimerQueueTimer: DueTime, Period, Flags
-- flag WT_EXECUTEONLYONCE = 8, timer will stops, enabled set to false
local mt = timer(1000, 1000, 0)
local i = 0;
function myOnTimer()
print('wow!')
if i < 5 then
i = i + 1
else
print("stopping timer")
mt:StopTimer()
end
end
mt:SetEvent('OnTimer', myOnTimer)
mt:StartTimer()
当我使用
while mt:GetEnabled() do --more buggy way
end
有“未处理的异常”,但它wow!
每秒不间断地打印。
和
while true do --buggy way, stack conflict during callback?
local enabled = mt:GetEnabled()
if not(enabled) then
break
end
end
5: bad argument #-2 to 'GetEnabled' (attempt to concatenatetimerLOADLIB: a table valuetimerstring)
或或之类的错误5: bad argument #-2 to 'GetEnabled' (timer expected, got table)
可以工作,直到来自 dll 的第一个事件并在没有错误的情况下停止。
仅有的
function WaitForTimer()
while true do
local is_enabled = mt:GetEnabled()
if not(is_enabled) then
print("not enabled")
return coroutine.yield()
end
end
end
co = coroutine.create(WaitForTimer)
coroutine.resume(co)
工作没有错误。
GetEnabled()
非常简单的静态 cdecl 函数的 dll 实现
function StaticThunk(L: Plua_State): integer; cdecl;
var
o: TLuaWrapper;
begin
o := TLuaWrapper(lua_topointer(L, lua_upvalueindex(1)));
result := o.Thunk(L);
end;
提取对象,对象的 Thunk
function TLuaWrapper.Thunk(L: Plua_State): integer;
var
i: integer;
pobj: PtrT;
begin
{ redirect method call to the real thing }
i := lua_tointeger(L, lua_upvalueindex(2)); // function's index, index is 2 since 1 is self ptr now
lua_pushnumber(L, 0);
lua_gettable(L, 1); // get the class table (i.e, self)
pobj := PtrT(luaL_checkudata(L, -1, PAnsiChar(REG_NAME)));
lua_remove(L, -1); // remove the userdata from the stack
lua_remove(L, 1); // remove object from the stack
try
result := ClassApiArray[i].func(L, pobj^); // execute the thunk
except
result := 0;
end;
end;
并且准确
function TLuaWrapper.GetEnabled(L: Plua_State; obj: TQueuedTimer): integer;
begin
// lua_settop(L, 0);
lua_pushboolean(L, obj.Enabled);
result := 1;
end;
Lua 内部究竟发生了什么?为什么我有冲突?
更多信息:在lua.exe
from下执行的脚本LuaForWindows
。