Lua
Lua(ルア)はスクリプト言語およびその処理系の実装で、主にリオデジャネイロ・カトリカ大学のコンピュータ科学科 (Department of Computer Science) および/または同大学附属研究所のTecgraf/PUC-Rio[注 1]に所属するロベルト・イエルサリムスキー Roberto Ierusalimschy[3][4]、Waldemar Celes[5][6]、Luiz Henrique de Figueiredo[7]らによって設計開発された[11]。 手続き型言語として、またプロトタイプベースのオブジェクト指向言語としても利用することができ、関数型言語としての要素も併せ持っている[12]。 名称の由来Luaという名前は、ポルトガル語の「月」に由来する。もともとLuaはブラジルの石油会社であるペトロブラス内部でデータ入力用に開発された言語DEL (data entry language) と、レポート生成用に開発されたSOL (simple object language) の2つの簡易言語に由来する。SOLがポルトガル語で太陽を意味することから、新しい言語の名称はLua(月)になった[13]。 概要Luaは、C言語のホストプログラムに組み込まれることを目的に設計されており、高速な動作と、高い移植性、組み込みの容易さが特徴である。いったんバイトコードにコンパイルされ、Lua VMで実行される。LuaJITは The Computer Language Benchmarks Game によると、動的型付けのスクリプト言語では最速の言語・処理系である[14]。 TIOBE Programming Community Indexでは2007年に人気が急上昇し、2011年6月には10番目に人気なプログラミング言語になったが、その後は人気が下がっている[15]。2009年2月の調査で、ゲーム開発者がイベントスクリプト等の内部処理に利用する言語として、最も利用例が多いと報告されるなど、近年[いつ?]はゲーム産業での利用が広がっている[16]。2013年3月以来、ウィキメディア財団のサイトではLuaをサポートしている[17]。 特徴Luaの特徴としては、汎用性が高いが比較的容易に実装が可能である、というものである。実際のところLuaは、オブジェクト指向などといった他の要素としての働きを明白にはサポートしていないが、サポートしていない範囲においても容易に拡張が可能である。また前述のような、動作の高速性や優れた移植性なども大きな特徴である。 文法的な特徴としては、Pascalによく似た構文を採用していること、コルーチン(協調的マルチタスク)のサポート[19]、数値型は整数と浮動小数点数の区別がないこと(ただしLua 5.3では整数型が導入された)、関数を変数として扱えることなどが挙げられる。 Luaはいわゆる汎用スクリプト言語であり、特定の用途に限定されない性質を持つが、同じく汎用スクリプト言語であるPerl、Python、Rubyと比較して高速に動作する[要出典]。これはLuaの理念である、簡素、高効率、高移植性を目指した実装の産物である。また、Luaにおけるテーブル(連想配列)の実装はかなり最適化されており、特にキーに数値のみを使用した場合は、単純な配列としてさらに高速に動作するようになる。 Lua 5.0以前はメモリ管理にマーク & スイープ方式のガベージコレクションが使用されていたが、Lua 5.1ではメモリ管理にインクリメンタル・ガベージコレクションが採用され、リアルタイム用途における性能の改善が図られている。ガベージコレクションの実装形態も Lua の高速動作および高リアルタイム性能に一役買っている。 LuaJITLuaのJITコンパイラである LuaJITがMike Pallにより開発されている。動的型付けであるにもかかわらず、Javaよりも少し遅くなる程度の速度で動いている[14]。静的単一代入などをつかった高度な最適化が行われており、バイトコードを実行する場合と比べて、数倍から数100倍の高速化が期待できる[20]。 Luaの歴史Lua
LuaJIT
コード例Hello Worldprint("Hello World")
-- `--´から行末までコメント
local a = {5, 3, 1, 4, 2} -- `{´と`}´はテーブルコンストラクタ
for i = 2, #a do -- `#´は長さ演算子であり、`#a´はテーブルaのサイズ(ここでは5)を返す
for j = i, 2, -1 do
if a[j - 1] <= a[j] then break end
a[j], a[j - 1] = a[j - 1], a[j]
end
end
コルーチンコルーチンは状態遷移を記述するのに便利である。 -- Lua コルーチンによって非同期の状態遷移を同期的に記述する例。
-- 1を返している間は動作を続行中。0を返すと動作を完了。
function doAction()
-- 4フレーム分だけ左へ移動。
for i = 1, 4, 1 do
print("Move Left " .. i)
coroutine.yield(1)
end
-- 1フレーム分だけ一時停止。
print("Pause")
coroutine.yield(1)
-- 3フレーム分だけ右へ移動。
for i = 1, 3, 1 do
print("Move Right " .. i)
coroutine.yield(1)
end
print("End")
return 0
end
local doActionAsync = coroutine.wrap(doAction)
-- コルーチンの動作テスト。
-- 実際にはフレームごとに1回だけ呼び出す。
while doActionAsync() ~= 0 do
end
正規表現LuaはPOSIXやECMAScript標準の正規表現とは異なる独自のカスタムパターンマッチングをサポートする[21]。 local myTable = {
"Gnome,160,30",
"Sylph,100,70",
"Salamander,200,20",
"Ondine,140,60",
}
for i = 1, #myTable do
local name, hp, mp = string.match(myTable[i], "([^,]+)%,([^,]+)%,(.+)")
print(string.format("Name = %q, HP = %d, MP = %d", name, tonumber(hp), tonumber(mp)))
end
LuaとC/C++の相互運用LuaにはC言語向けの相互運用APIが用意されている。LuaからC/C++の関数を呼び出すためには以下の方法を用いる。下記のコードはC/C++の関数をLua VMに登録し、Luaスクリプト側から呼び出している。 #include <cstdio>
#include <cstdlib>
#include <lua.h>
#include <lauxlib.h>
int my_add(lua_State* L) {
const int x = (int)lua_tonumber(L, 1); // 第1引数の取得。
const int y = (int)lua_tonumber(L, 2); // 第2引数の取得。
lua_settop(L, 0); // スタックのクリア。
const int ret = x + y; // C/C++ 側での演算。
lua_pushnumber(L, ret); // 返却値をプッシュ。
return 1;
}
int main(int argc, char* argv[]) {
lua_State* L = luaL_newstate(); // Lua VM の初期化。
luaL_openlibs(L); // Lua の標準ライブラリを使えるようにする。
lua_register(L, "my_add", my_add); // Lua VM に C/C++ 関数を登録。
// my_add 関数を呼び出す Lua スクリプトを実行。
if (luaL_dostring(L, "print(my_add(5, 3))")) {
lua_close(L); // Lua VM を閉じる。
return EXIT_FAILURE; // エラー終了。
}
lua_close(L);
return EXIT_SUCCESS;
}
逆に、C/C++からLuaの関数を呼び出す際にもスタック操作が必要となる。 #include <cstdio>
#include <cstdlib>
#include <lua.h>
#include <lauxlib.h>
int main(int argc, char* argv[]) {
lua_State* L = luaL_newstate(); // Lua VM の初期化。
// add_func 関数を定義する Lua スクリプトを実行。
if (luaL_dostring(L, "function add_func(x, y) return x + y end")) {
lua_close(L); // Lua VM を閉じる。
return EXIT_FAILURE; // エラー終了。
}
lua_getglobal(L, "add_func"); // Lua のグローバルオブジェクトである「add_func」を取得し、スタックに積む。
lua_pushinteger(L, 5); // 整数値の「5」を Lua スタックにプッシュ。
lua_pushinteger(L, 3); // 整数値の「3」を Lua スタックにプッシュ。
lua_call(L, 2, 1); // Lua 側で実装した add_func 関数を呼び出す。引数の数は2、結果の数は1。
printf("Result: %d\n", lua_tointeger(L, -1)); // 結果を表示。
lua_close(L);
return EXIT_SUCCESS;
}
言語バインディングの例Luaの他言語用バインディングは公式には提供されていないが、有志によるサードパーティ製ライブラリやツールがいくつか存在する。バインディングを使うと、前述のような煩雑なスタック操作を明示的に記述することなく、簡潔に相互運用できるようになる。 C++LuaをC++言語で記述されたホストプログラムへ組み込むための省力化ツール(コードジェネレーター)および言語バインディングとして、toLua[22]、 tolua++(Lua 5.2非対応)[23][24]、Luabind(Lua 5.2非対応)[25]、Selene[26]、Sol[27]、Sol2[28]などが開発されている。 以下にSol2を使った例を示す(C++11およびC++14の機能を利用するため、対応コンパイラが必要)。
#include <iostream>
#include <sol.hpp>
int add(int x, int y) {
return x + y;
}
int main() {
// Luaの初期化
sol::state lua;
// Luaの標準ライブラリをすべて開く
lua.open_libraries(sol::lib::base, sol::lib::coroutine, sol::lib::debug, sol::lib::debug,
sol::lib::io, sol::lib::math, sol::lib::os,
sol::lib::package, sol::lib::string, sol::lib::table, sol::lib::utf8);
// LuaにC/C++の関数を登録
lua["add"] = add;
// Luaスクリプトの読み込み
try {
lua.safe_script_file("test.lua");
} catch (const sol::error& e) {
std::cout << e.what() << std::endl;
}
}
C/C++の関数を呼び出すLuaスクリプト (test.lua): print(add(100, 200)) -- 「300」と表示される
#include <iostream>
#include <sol.hpp>
int main() {
// Luaの初期化
sol::state lua;
// Luaの標準ライブラリをすべて開く
lua.open_libraries(sol::lib::base, sol::lib::coroutine, sol::lib::debug, sol::lib::debug,
sol::lib::io, sol::lib::math, sol::lib::os,
sol::lib::package, sol::lib::string, sol::lib::table, sol::lib::utf8);
// Luaスクリプトの読み込み
try {
lua.safe_script_file("test.lua");
} catch (const sol::error& e) {
std::cout << e.what() << std::endl;
}
// Luaの関数を呼び出す
sol::function_result ret = lua["add"](100, 200);
// 結果を表示する
std::cout << ret.get<int>() << std::endl;
}
C++から呼び出される関数を定義するLuaスクリプト (test.lua): function add(a, b)
return a + b
end
JavaLuajというJava仮想マシン向けの実装がある。Luaj 3.0は、Lua 5.2相当の仕様をJavaで実装しなおしたものであり、Javaのクラスからバインダ無しでインスタンスを生成したりメソッドを呼び出したりすることが可能である。そのほか、LuaのC APIをJNI経由でJavaから利用可能にするJNLua[29]が存在する。 .NETC#やVB.NETといった.NET Framework言語向けのバインディングとして、LunaRoad[30]が存在する。C#で書かれたLuaインタプリタとしてMoonSharp[31]が存在する。また、DLR上に実装されたNeoLua[32]が存在する。 Luaを採用している製品ゲーム
ゲーム以外
脚注注釈
出典
関連書籍
関連項目
外部リンク
|