マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

PandocでWindowsをシャットダウンする件について

皆さんもよくご存知の通り、LuaLaTeXでは「Windwosをシャットダウンする文書」が作成できます。これはLuaコードを通じて(C言語コンパイルして生成した)マシン語のプログラムが実行できることを利用しています。

ところで、以前のネタで紹介した通り、PandocではLuaでフィルターを実装することができます。となると、マークダウンという不思議な形式の文書でWindowsをシャットダウンしてみたくなるのは当然の帰結でしょう。

どうもPandocでWindowsをシャットダウンできそうにない件

Luaでバイナリ(マシン語)のモジュールを作製する際には、次のような感じのC言語の関数を実装します。

※以下のコードはLuaLaTeXのやつで使っているモジュール1ソースコードからの抜粋。

/* Opens the module.
 */
__declspec(dllexport) int luaopen_shutwindown(lua_State *L) {
    luaL_newlib(L, registry);
    return 1;
}

Luaでモジュールを読み込む(require "shutwindown")と、この関数が実行されるのですが、この中で使われているluaL_newlibというのは「Lua処理系の連携用API」の一つです。連携APILua処理系と外部のコードの間のやり取りを行う機構で、バイナリのモジュールの実装に不可欠なものです。

つまり、バイナリのモジュールを動作させるには、Lua処理系の連携APIの関数が「外から見えている」必要があるわけです。TeX Live配布におけるLuaTeXのLua処理系は動的リンクのライブラリ(WindowsだとDLL形式)になっているため、連携APIは外から見えています。これに対して、Pandocの公式のWindwos用バイナリではLua処理系が静的にリンクされていて連携APIが外から見えません。これではLuaTeXの時と同じようには「Windowsをシャットダウンするモジュール」を実装することはできません。

それでもPandocでWindowsをシャットダウンしたい件

絶望的な状況になっていしまいましたが、もう少し考えてみましょう。

先程述べた通り、Luaコードにおいてモジュールshutwindownの読込(require)を行うとC言語の関数luaopen_shutwindownが呼ばれます。Luarequire "shutwindown"に対応する動作なので、通常はこの関数では「モジュールの関数を収めたLuaテーブルを作成して返す」ことが期待されています。しかし、とにかくモジュールの実装コードに実行を移すことができているのだから、ここで早々とシャットダウン開始の処理を済ませてしまえばいいわけです。

/* Opens the module.
 */
__declspec(dllexport) int luaopen_shutwindown(void *L) {
    shutdown_system(); /* シャットダウン! */
    return 0;
}

すなわち、このモジュールがインストールされたLua処理系では、require "shutwindown"を実行するだけでシャットダウンが開始します。

改めてPandocでWindowsをシャットダウンする件

というわけで、作ってみました

このリポジトリにあるファイルpcshutwindown.dllとshutdown.luaをカレントディレクト2に置いた上で、何か適当なMarkdown文書’(リポジトリにあるREADME.mdでもいいでしょう)をPandocで変換しましょう。もちろんフィルタにshutdown.luaを指定することを忘れずに。

C>pandoc README.md --lua-filter shutdown.lua
System will be shutdown in 10 seconds...
System will be shutdown in 9 seconds...
System will be shutdown in 8 seconds...
System will be shutdown in 7 seconds...
System will be shutdown in 6 seconds...
System will be shutdown in 5 seconds...
System will be shutdown in 4 seconds...
System will be shutdown in 3 seconds...
System will be shutdown in 2 seconds...
System will be shutdown in 1 second...
FAREWELL!

f:id:zrbabbler:20190616011206p:plain

まとめ

結局、PandocのLuaフィルタでバイナリモジュールを利用するのは難しい、のかな?


  1. 当該の記事を書いたときには、当時のLuaTeXに合わせてLua 5.1版を前提にした実装でしたが、現在(TeX Live 2019以降)のLuaTeXのLua処理系は5.3版であるため、5.3版で動作するように改修しました。

  2. Pandocの公式バイナリではLuaのバイナリモジュール読込パスにはカレントディレクトリが含まれています。