トップページ
ひらく | たたむ | ページトップ
↓マウスで反転選択した文字を検索
Lua
   
ページ内検索 ページ外検索
検索したい文字を入力して
ENTERを押すと移動します。
\n
[ トップページ ]
[ ____CommandPrompt ] [ ____JScript ] [ ____MySQL ] [ ____Cygwin ] [ ____Java ] [ ____Emacs ] [ ____Make ] [ ____Perl ] [ ____Python ] [ ____OpenGL ] [ ____C# ] [ ____StyleSheet ] [ ____C++ ] [ ____Winsock ] [ ____Thread ] [ ____VisualStudio ] [ ____C ] [ ____Win32API ] [ ____Lua ] [ ____PhotoShop ]
ヘッダ検索
___

■ C++のクラスをバインドする


    // テストクラス
    class Test 
    {
      int _x;
     public:
      Test(int x) : _x(x) {
        printf("ctor: %p, %d\n", this, _x);
      }
      ~Test() {
        printf("dtor: %p\n", this);
      }
      void talk() {
        printf("talk(), %p, %d\n", this, _x);
      }

      void *operator new ( size_t sz, void *mem ) {
        return mem;
      }
    };
メソッドをコールするために lua へバインドするための関数でラップする。

    static int l_talk(lua_State* L) 
    {
      // ユーザデータ(ポインタ)を Lua Script からもらう。
      Test* p = (Test*)lua_touserdata(L, -1);

      // メソッド本体をコール
      p->talk();

      // 戻り値の数
      return 0;    
    }
Lua から new をしたら, C++ 側では実際にオブジェクトを作成する。 さらにメソッドをフィールドアクセスの構文( p.method() )で呼べるように __index を指定したメタテーブルをオブジェクトに設定する。

    int l_new( lua_State *s )
    {
      // Lua 側から数値パラメータを一個もらう。
      int i = lua_tonumber( s, -1 );

      // オブジェクトを new して、そのポインタを Luaスタックに積む。
      void *p = lua_newuserdata ( s, sizeof( Test ) );
      void *q = new(p) Test( i );

      // クロージャで関連づけたテーブルを取り出し、
      lua_pushvalue( s, lua_upvalueindex(1));
      //  メタテーブルとして設定する
      lua_setmetatable( s, -2);


      // ポインタを Lua Script 側へ返す。
      // これで Lua 側からオブジェクトをハンドルできる。
      return 1;
    }
Lua からは次のように作成する。
      -- オブジェクトを生成して、ハンドルをもらう。
      -- Test テーブルの new メソッドをコールする。
      local p = Test.new( 5 );


      -- 操作したいハンドルを指定してメソッドをコールする。
      -- オブジェクト p に対して p.talk と書けるのはフィールドアクセス( __index )をオーバーライドしたから
      p.talk( p );


      -- : を利用することで、第一引数を省略できメソッド的な記述ができる。
      -- やっているのは上と同じ。
      p:talk();


      -- 別オブジェクトをつくる。
      local p2 = Test.new( 3 );
    void defclass( lua_State *s )
    {

      // クラスをテーブルとして生成
      lua_newtable( s );

            // ユーザデータで共有するメタテーブル用テーブル作成
            //  インスタンス毎に setmetatable される
            lua_newtable( s );

                // __index をオーバーライドすることで  obj.method() という記述した( フィールドアクセス )時に
                // メソッド用関数のテーブルを参照させる。
                // setfield によって値がポップするためコピーしておく。
                lua_pushvalue(s, -1);    // メタテーブル自身
                lua_setfield( s, -2, "__index");


                // クラスのメソッドをテーブルを登録しておく
                lua_pushcfunction( s, l_talk );
                lua_setfield( s, -2, "talk");


            // テーブルを上位値としてクロージャ生成
            // 後で new() をした時にテーブルを取り出し instance のメタテーブルとして設定する。
            lua_pushcclosure( s, l_new, 1);
            lua_setfield( s, -2, "new");


       // 生成したクラス(テーブル)を Test という名前でグローバル変数に公開
       lua_setglobal( s, "Test");
    } 

















NINJAIDX 18