編集: LuaJ自体を変更せずにLuaJのスレッドを安全に終了する方法が見つかりませんでした。LuaJでは動作しませんが、私が思いついたのは次のとおりです。ただし、純粋な Lua で機能するように簡単に変更できます。LuaJ スレッドは非常に問題があるため、Java 用の Python バインディングに切り替えている可能性があります。
--- 以下を思いついたのですが、LuaJ では動作しません ---
これが可能な解決策です。「カウント」イベントでトリガーされる debug.sethook を使用してフックを登録します (これらのイベントは でさえ発生しますwhile true do end
)。また、スクリプトを終了するかどうかを示すブール値フラグを含む、作成したカスタム「ScriptState」Java オブジェクトも渡します。Java オブジェクトは、フラグが設定されている場合、エラーをスローしてスクリプトを閉じる Lua フックで照会されます (編集: エラーをスローしても、実際にはスクリプトは終了しません)。終了フラグは、Lua スクリプト内から設定することもできます。
揺るぎない無限ループを自動的に終了したい場合は、ScriptState への呼び出しが最後に行われた時間を記録するタイマー システムを実装し、API 呼び出しなしで十分な時間が経過した場合にスクリプトを自動的に終了するのは簡単です(編集: これでのみ機能します)。スレッドを中断できる場合) . 無限ループを強制終了したいが、特定のブロック操作を中断したくない場合は、ScriptState オブジェクトを調整して、自動終了などを一時的に一時停止できる他の状態情報を含めることができます。
interpreter.lua
これは、必要に応じて別のスクリプトを呼び出して中断するために使用できるmyです。Javaメソッドを呼び出すため、変更しない限りLuaJ(または他のLua-Javaライブラリ)なしでは実行されません(編集:再び、純粋なLuaで動作するように簡単に変更できます)。
function hook_line(e)
if jthread:getDone() then
-- I saw someone else use error(), but an infinite loop still seems to evade it.
-- os.exit() seems to take care of it well.
os.exit()
end
end
function inithook()
-- the hook will run every 100 million instructions.
-- the time it takes for 100 million instructions to occur
-- is based on computer speed and the calling environment
debug.sethook(hook_line, "", 1e8)
local ret = dofile(jLuaScript)
debug.sethook()
return ret
end
args = { ... }
if jthread == nil then
error("jthread object is nil. Please set it in the Java environment.",2)
elseif jLuaScript == nil then
error("jLuaScript not set. Please set it in the Java environment.",2)
else
local x,y = xpcall(inithook, debug.traceback)
end
フラグとデモンストレーションを格納するScriptState
クラスは次のとおりです。main()
public class ScriptState {
private AtomicBoolean isDone = new AtomicBoolean(true);
public boolean getDone() { return isDone.get(); }
public void setDone(boolean v) { isDone.set(v); }
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
System.out.println("J: Lua script started.");
ScriptState s = new ScriptState();
Globals g = JsePlatform.debugGlobals();
g.set("jLuaScript", "res/main.lua");
g.set("jthread", CoerceJavaToLua.coerce(s));
try {
g.loadFile("res/_interpreter.lua").call();
} catch (Exception e) {
System.err.println("There was a Lua error!");
e.printStackTrace();
}
}
};
t.start();
try { t.join(); } catch (Exception e) { System.err.println("Error waiting for thread"); }
System.out.println("J: End main");
}
}
res/main.lua
実行するターゲット Lua コードが含まれています。通常どおり、環境変数またはパラメーターを使用して、追加情報をスクリプトに渡します。Lua でライブラリを使用する場合は、JsePlatform.debugGlobals()
代わりにを使用することを忘れないでください。JsePlatform.standardGlobals()
debug
os.exit()
編集: Lua スクリプトだけでなく、呼び出しプロセスも終了することに気付きました。と同等のようですSystem.exit()
。error()
エラーがスローされますが、Lua スクリプトが終了することはありません。私は今、これに対する解決策を見つけようとしています。