OSXで Lua 5.0 を使うためのメモ。

  2005/11/20

Lua言語について

  ブラジル生まれの組み込みスクリプト言語です。
  luaの母体となるインタプリタはC言語でかかれていて他のプログラム(ホストプログラム)に組み込みできます。
  他のプログラムに 組み込まずに単体としても使うことができます(スタンドアロンのLua)。
  MITライセンス。
  
  Luaの配布サイトからソースをダウンロードできます。もちろんOSX でも動作します。
  非公式なものでは 別の人がコンパイルした OSX用のLuaフレームワーク もリリースされています。

Lua言語の配布元

■Lua フレームワーク版について

  • Lua5.02 の MacOSXフレームワーク版と ソース がある
  • おそらく
    #include <Lua/lua.h>
    #include <Lua/lualib.h>
    #include <Lua/lauxlib.h>
    と記述する!?

    ■Lua ソース版の インストール方法

    公式サイトからソースをダウンロードしてから
    ターミナルから...

      cd /lua-5.0.2
      ./configure
      make
      make so ←共有ライブラリにする場合。
      sudo make install
    usr/local/include には
    lualib.h
    lua.h
    lauxlib.h

    usr/local/lib には
    liblualib.a
    liblua.a

    がインストールされる。
    Xcode の リンカフラグは、 -llua -llualib のようになる。

    その他

    もし、Lua_test:0: table of contents for archive: /usr/local/lib/liblua.a is out of date; rerun ranlib(1) (can't load from it)
    というエラーメッセージが出たら、ターミナルから次のコマンドを入力。
    sudo ranlib /usr/local/lib/liblualib.a
    sudo ranlib /usr/local/lib/liblua.a
     

    テスト方法(Lua スタンドアロンのインタプリタを実行する)。

      lua-5.0.2/test ディレクトリにサンプルスクリプトがある。 ターミナルから...
      cd test      // test ディレクトリへ移動する。
      ./lua -hello.lua  // 単独lua インタプリタを実行。
      ./lua -i hello.lua // 引数-i 対話モードにはいる。「hello.lua」を実行している。
    結果
      Hello world, from Lua 5.0.2!
    他の例
    lua -i echo.lua にほんご
    lua -i echo.lua \343\201\253\343\201\273\343\202\223\343\201\224
    0 echo.lua
    1 にほんご
     >
    インタプリタの対話モード「>」を終了,中止するには、 「control 」+ 「c」 キーを押すか、
    ターミナルの、メニュー>ファイルから、「ブレークを送信」を選択すると、元のコマンドラインに戻れます。
    test ディレクトリには、他にもLuaのサンプルスクリプトがあり、色々試すことができます。


    サンプルプログラムについて

    (testディレクトリにあるものを、わかりやすい順に紹介)

    lua    Luaインタプリタ ← これを使う。
    luac    Luaコンパイラ
    (この2つはエイリアス)
     
    hello.lua 簡単なプログラム(HELLO WORLD)
    printf.lua printf関数を実装してみる
    cf.lua 温度の換算表を表示する (摂氏→華氏)
    life.lua コンウェイのライフゲーム
    sort.lua 2つの( after quicksort と、after reverse selection sort )ソート関数の実装。月名データを辞書順に並べ替える。
    echo.lua パラメータとして入力した引数を echo コマンドにより行単位として表示
    luac.lua luacの べアボーン
    globals.lua 使われているグローバル変数を表示
    readonly.lua 読み取り専用のグローバル変数を作る。
    env.lua 環境変数 を自動的に グローバル変数にする。
    undefined.lua 「未定義」のグローバル変数を捕捉する。
    trace-calls.lua トレースを呼ぶ
    trace-globals.lua グローバル変数に対して、トレースを行う。
    xd.lua 16進dump 出力する
    bisect.lua 非線形同等化を解決するための二等分方法
    factorial.lua 再帰処理しないで階乗計算
    fib.lua    キャッシュを使ったフィボナッチ関数
    fibfor.lua コルーチンとジェネレータを使ったフィボナッチ数
    sieve.lua コルーチンを使って、エラトステネスのふるい( sieve of of Eratosthenes)をプログラムする。
    table.lua ×テーブルデータを作り、全てのデータを同種類のアイテムごとにグループ分けする。
     

    C から lua を使うモデル

    OSX では ObjC++が使えるので、ソースの拡張子は 「.mm」にしておくと便利です。
    Lua5.0 では、チャンクのロードはすべて lua_load にまとめられてしまいました。
    それによって luaファイル名を指定して読み込む lua_dofile 関数 は非推奨になり、マニュアルから省かれました。

    しかし lua_load は 分かりにくいので、Lua 5.0 から lua_dofile を使いたいという場合は
    次のようにすると良いです。

    //-----------------------------
    // ここで extern "C" をしなければ、 Undefined Symbol エラーが出ます。
    extern "C"
    {
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
    }
    #include <iostream>

    int main()
    {
    lua_State *L=lua_open(); // lua_State *L には Lua の状態 が入っている。
    // lua_State *L=lua_open(stacksize);ではじまり lua_close(L); で終わる。

    luaopen_base(L); //Lua用ライブラリ の読み込み lua_dofile を使うために 必須
    luaopen_io(L); // Lua ioライブラリの読み込み 必須

    /* 他に、用途に合わせて読み込みます。
    luaopen_string(L); (文字列ライブラリ)
    luaopen_table(L); (テーブルライブラリ)
    luaopen_math(L); (数学ライブラリ)
    luaopen_debug(L); (デバッグライブラリ)
    */

    //LuaからC側の関数を利用する場合はこの段階で lua_register マクロを使って関数を登録する


    lua_dofile( L , "hello.lua" ); // Luaスクリプトファイルを読む。本当は lua_load 関数を使うべきです。
                 // このソースでは、hello.lua スクリプトの出力が終わるまではプログラムは進みません。
                 // そのため、並列処理を行うには コルーチン(協調的マルチスレッド)を使うらしいです。

    // lua スクリプトとやりとりする部分

    lua_close(L);//終わる
    }
    // -----------------------------
    結果(Xcode で実行した結果)
    Hello world, from Lua 5.0.2!

    なお、 Xcode を使っている場合、Luaスクリプトファイル (hello.lua)は、 コンパイルされたアプリケーションが作成される
    階層と同じディレクトリ に置いて下さい。

    cf.lua:6: attempt to index global `string' (a nil value)
    とエラーが出たら、luaopen_string(L); を追加してみる。



    概要

    Lua にはスタックという積み重ね構造のデータ概念があり、
    C言語とLua はこの スタックを通して 値をやりとりしている。
    はじめのうちは、スタックを意識せず、Lua側からはじめると良いと思います。

    lua_State *L には Lua の状態 が入っている。
    lua_State *L=lua_open();ではじまり lua_close(L); で終わる。
    Lua スクリプトを実行する場合、ファイル、文字列、バッファから、スクリプトの塊(チャンク)を読み込むことができる。
    lua_dofile(L,"test.lua");


    Luaの変数

    Luaのプログラムでは、大域(grobal)変数は宣言しなくても使える。
    Luaの変数には型がないが、値 には型が存在する。

    スタック要素で参照される型の種類 ( ブーリアン, スレッドは v5.0から追加された)
    nil null に相当する
    ブーリアン false / true
    数値  実数+整数が表現できる。
    文字列 シングルクオート,ダブルクオートで囲まれたもの, エスケープシーケンスも使える。 文字列を連結するときは 「..」2つのピリオドからなる、文字列連結演算子を使うらしい。
    Lua関数 Lua 側の関数
    C 関数 C言語側の関数
    ユーザデータ
    スレッド 
    テーブル  配列のように利用できる。 テーブルは連想配列で管理されている。

    Lua スクリプト から、C言語の関数を呼び出す


    Luaから呼び出せるC言語の関数は lua_CFunction 型で定義される必要があり typedef int (*lua_CFunction) (lua_State *L); の形をとる
    このCの関数をLuaに登録するためには、lua_register マクロを使う。

    C言語からLuaスクリプトのスタックにアクセスする

    Lua と C 言語で、スタックに対して同じ操作をする場合、C言語側から操作するほうが Lua よりも手間がかかる。

    以下 LuaのホストプログラムがC言語の場合に、C言語側からスタックにアクセスする関数について。

    スタックは下から順に1番目から数えられ、関数の返値を 積み重ねたり、値を取り出したりする。
  • C言語側から、スタックを操作する関数が用意されている。 ( 挿入、追加 、削除 , 起点変更, push , popなど)
  • C言語側から、 スタック要素の型を判別する関数も用意されている。これらは「lua_is〜」から始まる関数。
  • C言語側から、C言語の値としてスタックから取り出すための関数が用意されている。これらは「lua_to〜」 で始まる関数 
  • C言語側から、値をスタックに積む関数が用意されている。これらは「lua_push〜」で始まる関数 
  • C言語側から、スタック内の2つの値を比較する関数も用意されている。

    Luaの変数について。Luaのプログラムでは、大域(grobal)変数は宣言しなくても使える。
    Luaの変数には型がないが、値 には型が存在する。

    スタック要素で参照される型変数の種類 ( ブーリアン, スレッドは v5.0から追加)
    nil  、 ブーリアン 、 数値  、文字列   、 Lua関数 、 C 関数 、 ユーザデータ 、 スレッド、 テーブル

    C言語側から、テーブル操作をする関数が用意されている


    ■C言語側から、Lua スクリプトの関数を呼び出すことができる。
    関数の返値や、引数がいくつあるかの整合性を考えておかなければいけない。
    C言語のほうが同じことをやるにしても手間がかかる。

    1) 呼びたい関数をスタックに積む。○○■
    2) その関数への引数を順番通りにスタックに積む○○□■■
    3) 最期に void lua_call (lua_State *L, int スタックに積んた引数の数 nargs , int 返値の数 nresults); を呼び出す。
           ↓
    4) 関数呼び出しに成功した場合、呼びたい関数,関数への引数は、スタックから削除され、
    関数結果の nresults ぶんだけ、返値がスタックに積まれる。○○▲▲▲



    ■Lua スクリプト から、Lua スクリプト関数を呼び出す (準備中)
  • 参考サイト

  • Lua - 機能拡張のためのプログラミング言語 概要 と紹介
  • Lua5.0リファレンス日本語
  • Lua ←→ C言語間の相互 呼び出し (Radium Software)0185
  • Luaチュートリアル(-divine relics-20040219)
  • MacOSXLua Lua の OSX 関連情報
  • Lua.Framework Lua5.02 の MacOSXフレームワーク版 と、ソースファイル
  • Lua.wiki のチュートリアル

  • Tsukubado