LuaとLuabindでiPhoneプログラミング
LuaとLuabindを使ってiPhoneアプリケーションを作成するメモです。
ここではLua5.1.4およびLuabind0.9を使用しました。
関連ライブラリのインストール
Lua, Boost, Luabindがまだインストールできていない場合はインストールします。MacPortsを使用するのが比較的早いようです。
また、.bashrcと.zshrcをこのページを参考に設定しておきます。
export PATH=/opt/local/bin:/opt/local/sbin/:$PATH export MANPATH=/opt/local/man:$MANPATH export LIBRARY_PATH=/opt/local/lib:$LIBRARY_PATH export LD_LIBRARY_PATH=/opt/local/lib:$LD_LIBRARY_PATH export C_INCLUDE_PATH=/opt/local/include:$C_INCLUDE_PATH export CPLUS_INCLUDE_PATH=/opt/local/include:$CPLUS_INCLUDE_PATH export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib export BOOST_ROOT=/opt/local/include/boost:$BOOST_ROOT
つぎにLuabindをインストールします。
これもMacPortsから入れようとしたけどまだ使用できないみたいなので、サイトからダウンロードして直接luabindディレクトリを/opt/local/include/にコピーします。
% sudo cp -r luabind /opt/local/include/
iPhone (ARM) 用ライブラリの作成
iPhone用にLuaとLuabindのライブラリ(.a)を作成します。さらに、デバイス用とシミュレータ用の2種類も同時に作ります。
※プロジェクトの種類はCocoa Touch静的ライブラリとします。
lua.hppの編集
#if __cplusplus extern "C" { #endif #include "lua.h" #include "lualib.h" #include "lauxlib.h" #if __cplusplus } // extern "C" #endif
テストプロジェクトの作成
以上でインストールは完了です。テストプロジェクトを作成して試してみましょう。
プロジェクトを作成し、プロジェクトのヘッダ検索パスに/opt/local/includeを追加します。また、プロジェクトに先ほど作ったライブラリ libluabindarm.a および libluaarm.a を追加します。
以上のようにして使えるはずです。
L = luaL_newstate(); if(!L) { std::cout << "Failed to open lua\n"; return; } luaL_openlibs(L); luabind::open(L); luabind::module(L) [ ... 関数定義など ]; NSString *path = [[NSBundle mainBundle] pathForResource:[NSString stringWithCString:filename] ofTye:nil]; // ファイルを実行する if(luaL_loadfile(L, [path UTF8Sring]) || lua_pcall(L, 0, 0, 0)) { std::cout << "Failed to load\n"; }
補足
- nil.hppでエラーが出るときは、extern...の行をコメントアウトしても普通に動きました(保証はしませんが)。
- Luabindを実行するファイルは拡張子を .mm (Objective-C++) としてください。
- Luabindでバインドするクラス中でObjective-Cのクラスを使用したい場合は、そのクラス実装の拡張子を .mm とし、使用するObjective-Cのクラスのプロトタイプ宣言をclassキーワードで行うことで実現できます。
XCodeでLuaを使う
Luaのインストール
Luaのダウンロードページから最新版のソースをダウンロードしてきます。現時点ではlua-5.1.4.tar.gzでした。
ターミナルを開き、次のように適当なフォルダの中で解凍、インストールします。
tar -xzvf lua-5.1.4.tar.gz cd lua-5.1.4 make macosx make test sudo make install
これで/usr/local/includeの中にインクルードファイルが、bin/の中にライブラリが入るはずです。
XCodeで使う
準備
XCodeを開き、新規プロジェクトを作成します。ここではC++ Toolとしました。
Luaを使うための設定をします。まず、インクルードパスの設定をしましょう。
メニューからProject->Edit Active Target "XXXX"を選択します。
"Build"タブの"Header Search Paths"の項目を、"/usr/local/include"とします。これでluaのインクルードファイルが読み込めるようになります。
次に、ライブラリを読み込みます。同じウィンドウの"General"タブをクリックし、"Linked Libraries"にliblua.aライブラリを追加します。一覧には無いのでAdd Other...でパスを指定してやる必要があります。
これで完了です。
テスト実行
次のようなソースでテストしてみましょう。
// main.cpp #include <iostream> #include <lua.hpp> int main(int argc, char * const argv[]) { lua_State *L = luaL_newstate(); luaL_openlibs(L); luaL_dofile(L, "/.../hello.lua"); return 0; }
-- test.lua print("Hello, World!")
正しく実行できたでしょうか。
Objective-C++でLuaを使うときの注意点
Objective-C++を使ってLuaを扱うとき、そのまま
この場合、
#if __cplusplus extern "C" { #endif #include "lua.h" #include "lualib.h" #include "luaxlib.h" #if __cplusplus } // extern "C" #endif
ちなみに、Objective-C++を扱うときは.mとしていたソースをすべて.mmという拡張子に変えたほうがいいようだ。この2点を変更することによってObjective-C++からLuaを扱えるようになった。
glpngはどこにあるのか
GLpngはOpenGLでpng画像を読み込むのに便利なライブラリ。公式ダウンロードリンクが切れているのでどこにあるかわからない。
と、ネットを調べていたら以下の場所にあるとのこと。
ftp://ftp.usa.openbsd.org/pub/OpenBSD/distfiles/glpng-1.45/glpng.zip
とりあえずメモしておきます。
Visual C++でluabindを使ってみる
引き続いて、Visual C++でLuabindを使ってLuaスクリプトを実行してみたいと思います。
Luabindとは
Luabindとは、C++とLuaスクリプトをうまく結びつけるためのライブラリで、これを使うことでクラスの実装や関数のオーバーロードが簡単に出来ます。
ドキュメントを読んでいると英語を読まないでもなんとなく使い方がわかりますが、実際に使ってみましょう。
実行にはBoost 1.30以上が必要なようです。Visual C++をインストールしていれば既にあるはずですが。
Luabindの準備
最新のソースが上記のホームページからダウンロードできます。解凍フォルダを適当な場所に置き、Visual C++からインクルードディレクトリ(luabindを解凍したフォルダ)を指定してやると準備完了です。
新規プロジェクトをつくり、ソースファイルにluabindのsrcフォルダ以下のソースファイルを追加してやり、
#include <luabind/luabind.hpp>
としてやれば準備完了というやつです。
サンプルプログラム
それではサンプルプログラムをつくってみましょう。
#include <iostream> #include <lua.hpp> #include <luabind/luabind.hpp> #pragma comment(lib, "lua5.1.lib") void greet(const char* name) { std::cout << "My name is " << name << std::endl; } class MyClass { private: int val; public: MyClass(int num) { val = num; } void show(void) { show(0); } void show(int num) { std::cout << val + num << std::endl; } void show(const char *str) { std::cout << str << val << std::endl; } }; int main(int argc, char* argv[]) { // Luaを開く lua_State* L = luaL_newstate(); luaL_openlibs(L); // luabindを開く luabind::open(L); luabind::module(L) [ luabind::def("greet", (void(*)(const char*)) &greet), luabind::class_<MyClass>("MyClass") .def(luabind::constructor<int>()) .def("show", (void(MyClass::*)(void))&MyClass::show) .def("show", (void(MyClass::*)(int))&MyClass::show) .def("show", (void(MyClass::*)(const char*))&MyClass::show) ]; // Luaスクリプトを開く if(luaL_loadfile(L, "C:\\Lua\\test\\sample2.lua") || lua_pcall(L, 0, 0, 0)) { perror(lua_tostring(L, -1)); } // Luaを閉じる lua_close(L); getchar(); return 0; }
このluabind::となっているところでluabindを初期化、およびクラスや関数をバインドしています。詳しくは後で書くことにして、Luaスクリプトの方を書いていきましょう。
-- sample.lua -------------------------------------------------------------------------------- Name = "ちゃーちゃん" greet(Name) obj = MyClass(100) obj:show() obj:show(100) obj:show("The value is ")
Luabindを開く
Luabindは全体が"luabind"名前空間に属しています。そのため、スコープ解決子::を使って次のようにアクセスします。
luabind::open(L)
これによってLuabindをオープンします。
関数を登録するには次のようなコードを書きます。
luabind::module(L) [ luabind::def("greet", (void(*)(const char*)) &greet) ];
見た目は気持ち悪いけど、見ていてなんとなくわかります。関数ポインタの前の型キャストは、関数名がダブるほかの関数がなければ書かなくても問題ないです。他の関数を登録するにはコンマ(,)で区切って複数書きます。
クラスを登録するには次のようにします。
luabind::module(L) [ luabind::class_<MyClass>("MyClass") .def(luabind::constructor<int>()) .def("show", (void(MyClass::*)(void))&MyClass::show) ];
メンバ関数を.def関数で記述していきます。コンストラクタやデストラクタ、演算子のオーバーロードなども実装できるということで柔軟性が高いです。このあたりは後にまた付け加えるかもしれません。