拡張機能
このドキュメントはLuaJIT 2.1用です。バージョン固有のドキュメントについては、各gitブランチのdocディレクトリを確認してください。
LuaJITはLua 5.1と完全に上位互換性があります。すべての標準Luaライブラリ関数とLua/C API関数のフルセットをサポートしています。
LuaJITは、リンカー/動的ローダーレベルでLua 5.1とも完全にABI互換性があります。これは、標準のLuaヘッダーに対してCモジュールをコンパイルし、LuaまたはLuaJITから同じ共有ライブラリをロードできることを意味します。
LuaJITは標準のLua VMに新しい機能を拡張し、いくつかの拡張モジュールを追加しています。このページは機能拡張についてのみであり、最適化されたVM、より高速なインタプリタ、またはJITコンパイラなどのパフォーマンス向上については扱っていません。
拡張モジュール
LuaJITにはいくつかの組み込みの拡張モジュールがあります:
bit.* — ビット単位の操作
LuaJITはLua BitOpで定義されているすべてのビット単位の操作をサポートしています:
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
このモジュールはLuaJITの組み込みであり、Lua BitOpをダウンロードまたはインストールする必要はありません。Lua BitOpサイトには、すべてのLua BitOp API関数の完全なドキュメントがあります。FFIは同じAPI関数を使用して64ビットのビット単位の操作をサポートします。
モジュールを使用する前にrequireしてください:
local bit = require("bit")
既にインストールされているLua BitOpモジュールはLuaJITによって無視されます。この方法で、共有インストールからLuaとLuaJITの両方でビット操作を使用できます。
ffi.* — FFIライブラリ
FFIライブラリを使用すると、純粋なLuaコードから外部C関数を呼び出したり、Cデータ構造を使用したりできます。
jit.* — JITコンパイラ制御
このモジュールの関数は、JITコンパイラエンジンの動作を制御します。
C APIの拡張
LuaJITはLua/C APIにいくつかの追加関数を追加します。
プロファイラ
LuaJITには統合プロファイラがあります。
標準ライブラリ関数の強化
xpcall(f, err [,args...])
は引数を渡します
Lua 5.1の標準実装とは異なり、xpcall()
はエラー関数の後に任意の引数を保護されたコンテキストで呼び出される関数に渡します。
load*() はUTF-8ソースコードを処理します
非ASCII文字はLuaソースコードパーサーによって透過的に処理されます。これにより、識別子や文字列内にUTF-8文字を使用できます。UTF-8のBOMはソースコードの開始時にスキップされます。
load*() にモードパラメータを追加します
Lua 5.2からの拡張として、関数loadstring()
、loadfile()
、および(新しい)load()
はオプションのモードパラメータを追加します。
デフォルトのモード文字列は"bt"で、ソースコードとバイトコードの両方のロードを許可します。"t"を使用してソースコードのみを許可し、"b"を使用してバイトコードのみを許可します。
デフォルトでは、load*
関数はネイティブなバイトコード形式を生成します。クロスコンパイルの目的で、モード文字列にWを追加して32ビット形式を強制し、Xを追加して64ビット形式を強制します。両方を追加して反対の形式を強制します。load*
によって生成された非ネイティブなバイトコードは実行できませんが、string.dump
へ渡すことはできます。
tostring()
などはNaNと±Infを正規化します
すべての数値から文字列への変換は、非有限数をすべてのプラットフォームで同じ文字列に一貫して変換します。NaNは"nan"となり、正の無限大は"inf"となり、負の無限大は"-inf"となります。
tonumber()
などは組み込みの文字列から数値への変換を使用します
すべての文字列から数値への変換は、10進数、16進数、および2進数の整数および浮動小数点入力をすべてのプラットフォームで一貫して変換します。strtod()
はもはや使用されず、Cライブラリの実装が不十分である多数の問題を回避します。組み込みの変換関数はIEEE-754標準に従って完全な精度を提供し、現在のロケールに依存せず、16進浮動小数点数(例:0x1.5p-3)をサポートします。
string.dump(f [,mode])
は移植可能なバイトコードを生成します
string.dump()
には追加の引数が追加されました。これがtrueまたは文字sを含む文字列に設定されている場合、デバッグ情報のない「削除された」バイトコードが生成されます。これにより、後のバイトコードのローディングが速くなり、メモリ使用量が減少します。コマンドラインオプションの-b
も参照してください。
生成されたバイトコードは移植可能であり、LuaJITがサポートする任意のアーキテクチャでロードすることができます。ただし、バイトコードの互換性バージョンは一致している必要があります。バイトコードはメジャー+マイナーバージョン内でのみ互換性が保たれます(x.y.aaa → x.y.bbb)、開発ブランチを除く。外部のバイトコード(例えばLua 5.1からのもの)は互換性がなく、ロードすることはできません。
注意:LJ_GC64モードは異なるフレームレイアウトを必要とし、これは32ビットと64ビットのポート間で異なる、互換性のないバイトコード形式を意味します。これは将来修正されるかもしれません。その間は、クロスコンパイルの目的でload*関数のWおよびXモードを使用してください。
VMの強化により、バイトコードは決定的ではありません。同一のソースコードから常にバイト単位で同一のバイトコードダンプを得るために、モード文字列にdを追加して決定的な方法でダンプします。この機能は、再現可能なビルドに主に役立ちます。
table.new(narray, nhash) は事前サイズ指定されたテーブルを割り当てます
追加のライブラリ関数table.new()
はrequire("table.new")
を通じて利用可能にすることができます。これはC APIの同等物であるlua_createtable()
のように、事前サイズ指定されたテーブルを作成します。これは、最終的なテーブルサイズがわかっていて、自動テーブルリサイズが高価すぎる場合に大きなテーブルに役立ちます。
table.clear(tab) はテーブルをクリアします
追加のライブラリ関数table.clear()
はrequire("table.clear")
を通じて利用可能にすることができます。これはテーブルからすべてのキーと値をクリアしますが、割り当てられた配列/ハッシュのサイズは保持します。これは、複数の場所からリンクされているテーブルをクリアする必要がある場合や、同じコンテキストで使用するためにテーブルをリサイクルする場合に便利です。これにより、バックリンクの管理が不要となり、割り当てと増分配列/ハッシュ部分の成長のオーバーヘッドが節約されます。
この関数は非常に特定の状況を対象としています。ほとんどの場合、(通常は単一の)リンクを新しいテーブルに置き換え、GCに作業を任せる方がよいでしょう。
math.random()のための強化されたPRNG
LuaJITは、Tausworthe PRNGを使用してmath.random()
とmath.randomseed()
を実装しており、その周期は2^223です。このPRNGの結果の品質は、プラットフォーム固有のANSI rand()
を使用する標準のLua実装と比較して大幅に優れています。
PRNGは、すべてのプラットフォームで同じシードから同じシーケンスを生成し、シード引数のすべてのビットを使用します。引数なしでmath.random()
を呼び出すと、各呼び出しで52ビットの疑似ランダムビットを生成します。結果は0.0から1.0の間で均一に分布しています。math.random(n [,m])
用に正確にスケールアップされ、均一性を保つために丸められます。
重要:これを含む、単純なmath.random()
APIに基づく他のPRNGも、暗号利用には適していません。
io.*関数は64ビットファイルオフセットを扱う
標準のio.*ライブラリ内のファイルI/O関数は64ビットファイルオフセットを扱います。特に、2ギガバイトを超えるファイルを開くことが可能であり、2 GBを超えるオフセットに対して現在のファイル位置を再配置または取得することが可能です(fp:seek()
メソッド)。
debug.*関数はメタメソッドを識別する
debug.getinfo()
およびlua_getinfo()
は、呼び出されたメタメソッドに関する情報も返します。namewhat
フィールドは"metamethod"に設定され、name
フィールドには対応するメタメソッドの名前(例:"__index"
)が設定されます。
完全に再開可能なVM
LuaJIT VMは完全に再開可能です。これは、標準のLua 5.1 VMでは不可能なコンテキストを超えてコルーチンからyieldできることを意味します:例えば、pcall()
やxpcall()
を超えて、イテレーターやメタメソッドを超えてyieldすることができます。
Lua 5.2からの拡張機能
LuaJITはLua 5.2からのいくつかの言語とライブラリの拡張をサポートしています。既存のコードを壊す可能性が低い機能は無条件に有効になっています:
goto
と::labels::
。- 文字列内の16進エスケープ
\x3F
と\z
エスケープ。 load(string|reader [, chunkname [,mode [,env]]])
。loadstring()
はload()
のエイリアスです。loadfile(filename [,mode [,env]])
。math.log(x [,base])
。string.rep(s, n [,sep])
。string.format()
:%q
が逆変換可能。%s
は__tostring
をチェック。%a
と%A
が追加された。- 文字列マッチングパターン
%g
が追加された。 io.read("*L")
。io.lines()
とfile:lines()
はio.read()
のオプションを処理する。os.exit(status|true|false [,close])
。package.searchpath(name, path [, sep [, rep]])
。package.loadlib(name, "*")
。debug.getinfo()
はオプション"u"に対してnparams
とisvararg
を返す。debug.getlocal()
はレベルではなく関数を受け入れる。debug.getlocal()
とdebug.setlocal()
は可変引数に対して負のインデックスを受け入れる。debug.getupvalue()
とdebug.setupvalue()
はC関数を扱う。debug.upvalueid()
とdebug.upvaluejoin()
。- Lua/C APIの拡張:
lua_version()
lua_upvalueid()
lua_upvaluejoin()
lua_loadx()
lua_copy()
lua_tonumberx()
lua_tointegerx()
luaL_fileresult()
luaL_execresult()
luaL_loadfilex()
luaL_loadbufferx()
luaL_traceback()
luaL_setfuncs()
luaL_pushmodule()
luaL_newlibtable()
luaL_newlib()
luaL_testudata()
luaL_setmetatable()
- コマンドラインオプション
-E
。 - コマンドラインはエラーに対して
__tostring
をチェックする。
他の機能は、LuaJITが-DLUAJIT_ENABLE_LUA52COMPAT
でビルドされている場合にのみ有効にされます:
goto
はキーワードになり、もはや有効な変数名ではありません。break
はどこにでも配置できます。空のステートメント(;;
)が許可されます。- 異なるタイプの場合は
__lt
、__le
が呼び出されます。 - テーブルのための
__len
。rawlen()
ライブラリ関数。 pairs()
とipairs()
は__pairs
と__ipairs
をチェックする。coroutine.running()
は2つの結果を返す。table.pack()
とtable.unpack()
(unpack()
と同じ)。io.write()
とfile:write()
はtrueではなくファイルハンドルを返す。os.execute()
とpipe:close()
は詳細な終了ステータスを返す。debug.setmetatable()
はオブジェクトを返す。debug.getuservalue()
とdebug.setuservalue()
。math.mod()
、string.gfind()
を削除。package.searchers
。module()
はモジュールテーブルを返す。
注意
これは、言語とLuaライブラリレベルでLua 5.2との部分的な互換性のみを提供します。LuaJITはLua 5.1とAPI+ABI互換性があり、それによりLua/C APIとABIを壊す可能性のある機能(例:_ENV
)の実装が防がれます。
Lua 5.3からの拡張機能
LuaJITはLua 5.3からのいくつかの拡張をサポートしています:
- ユニコードエスケープ
\u{XX...}
は、文字列リテラル内にUTF-8エンコーディングを埋め込みます。 - 引数テーブル
arg
は、LUA_INITおよび-eチャンクによって読み取り(および変更)することができます。 io.read()
およびfile:read()
は、先頭に*があるかないかにかかわらずフォーマットを受け入れます。assert()
は任意のタイプのエラーオブジェクトを受け入れます。table.move(a1, f, e, t [,a2])
。coroutine.isyieldable()
。- Lua/C APIの拡張:
lua_isyieldable()
C++例外との相互運用
LuaJITには、C++の例外との相互運用をサポートする組み込みの機能があります。利用可能な機能の範囲は、ターゲットプラットフォームとLuaJITのコンパイルに使用されるツールチェーンに依存します:
プラットフォーム | コンパイラ | 相互運用性 |
---|---|---|
外部フレームアンワインディング | GCC, Clang, MSVC | 完全 |
内部フレームアンワインディング + DWARF2 | GCC, Clang | 限定 |
Windows 64ビット | 非MSVC | 限定 |
その他のプラットフォーム | その他のコンパイラ | なし |
完全な相互運用性とは:
- C++の例外は、
pcall()
、lua_pcall()
などのLua側でキャッチできます。 - C++の例外は、「C++例外」という一般的なLuaエラーに変換されますが、C呼び出しラッパー機能を使用しない限りです。
- 非保護Luaフレームを介してC++の例外をスローすることは安全です。C++例外オブジェクトの内容は変更されません。
- LuaエラーはC++側で
catch(...)
によってキャッチできます。対応するLuaエラーメッセージはLuaスタックから取得できます。 - C++フレームを超えてLuaエラーをスローすることは安全です。C++のデストラクタは呼ばれます。
限定的な相互運用性とは:
- C++の例外は、
pcall()
、lua_pcall()
などのLua側でキャッチできます。 - C++の例外は、「C++例外」という一般的なLuaエラーに変換されますが、C呼び出しラッパー機能を使用しない限りです。
- C++の例外は非保護Luaフレームによってキャッチされ、一般的なLuaエラーとして再スローされます。C++例外オブジェクトは破棄されます。
- C++側でLuaのエラーをキャッチすることはできません。
- C++のフレームを超えてLuaのエラーをスローすると、C++のデストラクタは呼び出されません。
相互運用性がないということは:
- Luaのフレームを超えてC++の例外をスローすることは安全ではありません。
- C++の例外はLua側でキャッチすることができません。
- LuaのエラーをC++側でキャッチすることはできません。
- C++のフレームを超えてLuaのエラーをスローすると、C++のデストラクタは呼び出されません。