次のような一般的なタイミングトリックを実行するためにluaを取得する方法がわかりません。
スリープ-スレッド上のすべてのアクションを停止します
一時停止/待機-次のコマンドには進まないが、アプリケーション内の他のコードの続行を許可する
ブロック-現在のコマンドが戻るまで次のコマンドに進まない
そして、私はそれを読んだ
while os.clock()<time_point do
--nothing
end
cPU時間を使い果たします。
助言がありますか?欠落しているAPI呼び出しはありますか?
[〜#〜] update [〜#〜]:ずっと前に、WOW Luaにスケジュールに従ってアクションを再生させるためにこの質問を書きました(つまり、立って、1秒待って、ダンスして、2秒待って、座ってください。休止なしで、これらはほぼすべて同じ四分の一秒で起こります。) ゲームを壊したり、ボットを有効にしたりする可能性があるため、時計を操作します。 時計を取り除いたら、時計を再作成することを考えました。アクションと実行時間)、マウスムーブなどの一般的なイベントのイベントハンドラーを登録し、イベントが発生したアクションを偶数ハンドラーで処理します。イベントハンドラは実際にはXミリ秒ごとに発生するわけではありませんが、2〜100ミリ秒ごとに発生する場合は十分に近いでしょう。悲しいことに私はそれを試したことがない。
これより簡単になることはありません。スリープはFLTKなどに実装できますが、これは特別なイベント割り込みなしで標準的な種類のシステムスリープを実行する最良の方法をすべて網羅しています。見よ:
-- we "pcall" (try/catch) the "ex", which had better include os.sleep
-- it may be a part of the standard library in future Lua versions (past 5.2)
local ok,ex = pcall(require,"ex")
if ok then
-- print("Ex")
-- we need a hack now too? ex.install(), you say? okay
pcall(ex.install)
-- let's try something else. why not?
if ex.sleep and not os.sleep then os.sleep = ex.sleep end
end
if not os.sleep then
-- we make os.sleep
-- first by trying ffi, which is part of LuaJIT, which lets us write C code
local ok,ffi = pcall(require,"ffi")
if ok then
-- print("FFI")
-- we can use FFI
-- let's just check one more time to make sure we still don't have os.sleep
if not os.sleep then
-- okay, here is our custom C sleep code:
ffi.cdef[[
void Sleep(int ms);
int poll(struct pollfd *fds,unsigned long nfds,int timeout);
]]
if ffi.os == "Windows" then
os.sleep = function(sec)
ffi.C.Sleep(sec*1000)
end
else
os.sleep = function(sec)
ffi.C.poll(nil,0,sec*1000)
end
end
end
else
-- if we can't use FFI, we try LuaSocket, which is just called "socket"
-- I'm 99.99999999% sure of that
local ok,socket = pcall(require,"socket")
-- ...but I'm not 100% sure of that
if not ok then local ok,socket = pcall(require,"luasocket") end
-- so if we're really using socket...
if ok then
-- print("Socket")
-- we might as well confirm there still is no os.sleep
if not os.sleep then
-- our custom socket.select to os.sleep code:
os.sleep = function(sec)
socket.select(nil,nil,sec)
end
end
else
-- now we're going to test "alien"
local ok,alien = pcall(require,"alien")
if ok then
-- print("Alien")
-- beam me up...
if not os.sleep then
-- if we still don't have os.sleep, that is
-- now, I don't know what the hell the following code does
if alien.platform == "windows" then
kernel32 = alien.load("kernel32.dll")
local slep = kernel32.Sleep
slep:types{ret="void",abi="stdcall","uint"}
os.sleep = function(sec)
slep(sec*1000)
end
else
local pol = alien.default.poll
pol:types('struct', 'unsigned long', 'int')
os.sleep = function(sec)
pol(nil,0,sec*1000)
end
end
end
elseif package.config:match("^\\") then
-- print("busywait")
-- if the computer is politically opposed to NIXon, we do the busywait
-- and shake it all about
os.sleep = function(sec)
local timr = os.time()
repeat until os.time() > timr + sec
end
else
-- print("NIX")
-- or we get NIXed
os.sleep = function(sec)
os.execute("sleep " .. sec)
end
end
end
end
end
[これを John Cromartie's postのコメントとして投稿するつもりでしたが、コメントでフォーマットを使用できないことに気づきませんでした。]
同意する。 os.execute()を使用してシェルにドロップすることは間違いなく機能しますが、一般的にシェル呼び出しを行うには費用がかかります。一部のCコードのラッピングは、実行時にはるかに高速になります。 LinuxシステムのC/C++では、次を使用できます。
static int lua_sleep(lua_State *L)
{
int m = static_cast<int> (luaL_checknumber(L,1));
usleep(m * 1000);
// usleep takes microseconds. This converts the parameter to milliseconds.
// Change this as necessary.
// Alternatively, use 'sleep()' to treat the parameter as whole seconds.
return 0;
}
次に、主に、次の操作を行います。
lua_pushcfunction(L, lua_sleep);
lua_setglobal(L, "sleep");
ここで、「L」はlua_Stateです。次に、C/C++から呼び出されたLuaスクリプトで、次を呼び出して関数を使用できます。
sleep(1000) -- Sleeps for one second
プロジェクトで LuaSocket を使用する場合、または単にインストールして使用する気にしない場合は、 socket.sleep(time)
関数を使用できます。一定時間(秒単位)スリープします。
これはWindowsとUnixの両方で機能し、追加のモジュールをコンパイルする必要はありません。
関数がパラメーターとして小数秒をサポートすることを追加する必要があります。つまり、socket.sleep(0.5)
は0.5秒スリープします。 Windowsでは Sleep()
を使用し、他の場所では nanosleep()
を使用するため、time
の場合はWindowsの精度に問題がある可能性があります低くなります。
CPUを消費せずに純粋なLuaでそれを行うことはできませんが、簡単で移植性のない方法があります。
os.execute( "sleep 1")
(ブロックします)
明らかに、これは「sleep 1」が有効なコマンドであるオペレーティングシステム、たとえばUnixでのみ機能しますが、Windowsでは機能しません。
windowsの場合、これを行うことができます:
os.execute("CHOICE /n /d:y /c:yn /t:5")
スリープ関数-使用法:sleep(1) -- sleeps for 1 second
_local clock = os.clock
function sleep(n) -- seconds
local t0 = clock()
while clock() - t0 <= n do
end
end
_
関数の一時停止-使用法:pause() -- pause and waits for the Return key
_function pause()
io.stdin:read'*l'
end
_
希望、これがあなたが必要なものです! :D-ジョーDF
Pure LuaはANSI標準Cにあるもののみを使用します。LuizFiguereidoの lposix module は、より体系的なことを行うために必要なものの多くを含んでいます。
ホストシステムのスリープ関数をCでラップする単純な関数を実装します。
require 'alien'
if alien.platform == "windows" then
kernel32 = alien.load("kernel32.dll")
sleep = kernel32.Sleep
sleep:types{ret="void",abi="stdcall","uint"}
else
-- untested !!!
libc = alien.default
local usleep = libc.usleep
usleep:types('int', 'uint')
sleep = function(ms)
while ms > 1000 do
usleep(1000)
ms = ms - 1000
end
usleep(1000 * ms)
end
end
print('hello')
sleep(500) -- sleep 500 ms
print('world')
Luaで処理を停止し、アプリケーションの実行を続ける2番目のリクエストである一時停止/待機には、コルーチンが必要です。次のようなCコードになります。
Lthread=lua_newthread(L);
luaL_loadfile(Lthread, file);
while ((status=lua_resume(Lthread, 0) == LUA_YIELD) {
/* do some C code here */
}
luaには次のものがあります。
function try_pause (func, param)
local rc=func(param)
while rc == false do
coroutine.yield()
rc=func(param)
end
end
function is_data_ready (data)
local rc=true
-- check if data is ready, update rc to false if not ready
return rc
end
try_pause(is_data_ready, data)
次を使用できます。
os.execute("sleep 1") -- I think you can do every command of CMD using os.execute("command")
または使用できます:
function wait(waitTime)
timer = os.time()
repeat until os.time() > timer + waitTime
end
wait(YourNumberHere)
スリープ機能のラッピングについてジョンに同意します。このラップされたスリープ関数を使用して、luaに一時停止関数を実装することもできます(スリープしてから、特定の条件が頻繁に変更されるかどうかを確認します)。別の方法は、フックを使用することです。
3番目の箇条書きであなたが何を意味するのか正確にはわかりません(通常、コマンドは次のコマンドが実行される前に完了しないのですか?).
参照: 質問:どうすればLuaスレッドをきれいに終了できますか? フックの使用例について。
win.Sleep(milliseconds)
、methinksが必要です。
ええ、あなたは間違いなくあなたが説明するような忙しい待ちをしたくありません。
Alienをlibc/msvcrtラッパーとして使用するのも簡単です。
> luarocks install alien
次に、luaから:
require 'alien'
if alien.platform == "windows" then
-- untested!!
libc = alien.load("msvcrt.dll")
else
libc = alien.default
end
usleep = libc.usleep
usleep:types('int', 'uint')
function sleep(ms)
while ms > 1000 do
usleep(1000)
ms = ms - 1000
end
usleep(1000 * ms)
end
print('hello')
sleep(500) -- sleep 500 ms
print('world')
警告:MSWindowsではこれを試していません。 msvcrtにusleep()があるかどうかさえわかりません
私はLuaから始めましたが、古き良きコマンドラインフラッシュだけではなく、結果を見たいと思いました。だから私はちょうど私のファイルに次の行を追加し、ちょっと標準、ちょっと:
please press any key to continue...
os.execute("PAUSE")
私のサンプルファイルは印刷物であり、一時停止の文ですので、ここに投稿する必要はないでしょう。
完全なスクリプトのプロセスを実行することのCPUの意味がわかりません。ただし、デバッグの途中でコードを停止すると便利です。
私はあなたが使用するかもしれない窓のために信じています:os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul
簡単なタイマーとして。 (ミリ秒単位で時間を挿入するときに「<>」を削除します)(コードの残りと>nul
の間にスペースがあります)
cy = function()
local T = os.time()
coroutine.yield(coroutine.resume(coroutine.create(function()
end)))
return os.time()-T
end
sleep = function(time)
if not time or time == 0 then
time = cy()
end
local t = 0
repeat
local T = os.time()
coroutine.yield(coroutine.resume(coroutine.create(function() end)))
t = t + (os.time()-T)
until t >= time
end
これは動作するはずです:
os.execute("PAUSE")