monozuku

PC、DIY、電子工作等の情報を発信しています

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 ")

ビルドにはかなり時間がかかりましたが、おそらく最適化を行っているためでしょう。成功すればつぎのようになるはずです。

クラスの実装および関数オーバーロードLua上でできていることがわかります。

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関数で記述していきます。コンストラクタやデストラクタ、演算子オーバーロードなども実装できるということで柔軟性が高いです。このあたりは後にまた付け加えるかもしれません。

Visual C++でLuaを使ってみる

本題

Luaとは、柔軟で高速なC言語に組み込めるスクリプト言語です。詳しい説明はここらへんに書いてあるので抜きにして、今回はVisual C++を使ってLuaを単体で使ってみようということで。

Luaをダウンロード

http://www.lua.org/のdownloadメニューから最新版をダウンロードできます。
http://code.google.com/p/luaforwindows/なんかをダウンロードするとエディタと実行環境もついてきますが、今回はVisual C++から使うということなので、Windows用のバイナリからlua5_1_4_Win32_vc9_lib.zipをダウンロードしました。
適当なフォルダ(C:\Lua\)をつくり、lua5.1.libをC:\Lua\libフォルダに、includeフォルダの中身をC:\Lua\includeフォルダに入れました。

Visual C++へのディレクトリの追加


Visual C++のツール->オプションから「VC++ディレクトリ」に先ほどのlibフォルダ(ライブラリ)、includeフォルダ(インクルード)を追加しましょう。これで設定は完了です。

テスト用プロジェクトの作成


新規プロジェクトで「Win32コンソールアプリケーション」を作成、「空のプロジェクト」にチェックを入れておきます。
新たなファイルmain.cppを追加し、次のソースコードを打ち込みます。

main.cpp
#include <stdio.h>
#include "lua.hpp"

#pragma comment(lib, "lua5.1.lib")

int main(int argc, char* argv[])
{
    // Luaを開く
    lua_State* L = luaL_newstate();

    // Lua標準関数を使う
    luaL_openlibs(L);

    // Luaファイルを読み込む
    if(luaL_loadfile(L, "c:\\Lua\\test\\sample.lua") || lua_pcall(L, 0, 0, 0)) {
        perror(lua_tostring(L, -1));
    }

    // 関数を読み込む
    lua_getglobal(L, "speech");
    if(lua_pcall(L, 0, 0, 0)) {
        perror(lua_tostring(L, -1));
    }

    // グローバル変数を読む
    lua_getglobal(L, "Name");
    if(lua_isstring(L, -1)) {
        printf("My name is %s.\n", lua_tostring(L, -1));
    }

    // Luaを閉じる
    lua_close(L);

    getchar();
    return 0;
}

lua5.1.libのあたりは使っているライブラリにあわせて変える必要があります。
Luaスクリプトも書いていきましょう。

sample.lua
-- sample.lua
--------------------------------------------------------------------------------

Name = "ちゃーちゃん"

print("Hello, " .. Name .. "!")

function speech()
    print("Is your name " .. Name .. "?")
end

ビルドして実行してみましょう。

詳しい説明

#include "lua.hpp"

C++用のLuaヘッダファイルです。この中では単にextern "C"して他のヘッダファイルを読み込んでいるようです。
あとはVC用にコンパイルされたライブラリをリンクするだけで、Luaが使えるようになります。
簡単すぎてびっくりしますね!

サンプルではスクリプトの実行、関数呼び出し、グローバル変数の取得を行っています。
あと、Luaスクリプト文字コードSJIS、改行コードはCRLFでした。

Luaスクリプトの文法や、C++などでどうやって利用するかなどもおいおい書いていきます。