. Lua


.Luaの特徴
2.データ交換の紹介
3.CとLuaスクリプトの相互呼び出し例
4.参考資料
1.Luaの特徴
Luaはコンパクトなスクリプト言語です.作者はブラジル人です.この言語の設計目的は、アプリケーションに埋め込まれ、アプリケーションに柔軟な拡張とカスタマイズ機能を提供することです.ホームページはwww.lua.org.
Luaの最も有名な応用は大雪会社のネットゲームWOWである.
Luaスクリプトは、C/C++コードによって容易に呼び出されてもよいし、C/C++の関数を逆に呼び出すこともでき、アプリケーションにおいてLuaを広く応用することができる.拡張スクリプトとしてだけでなく、XML、Iniなどのファイル形式の代わりに、通常のプロファイルとしても使用でき、理解とメンテナンスが容易になります.
Luaは標準Cで作成され、コードは簡潔で優美で、ほとんどのオペレーティングシステムとプラットフォームでコンパイルし、実行することができます.完全なLua解釈器は200 kにすぎず、現在のすべてのスクリプトエンジンの中でLuaの速度が最も速い.これらはすべてLuaが埋め込みスクリプトとして最適な選択であることを決定します.
Luaは、特定のプラットフォームでのインスタントコンパイル機能を提供するJITプロジェクトを同時に行い、Luaにより優れたパフォーマンスをもたらします.アクセスしてくださいhttp://luajit.luaforge.net/このプロジェクトを理解しに来ました.
Pythonなどのスクリプトとは異なり、Luaは強力なライブラリを提供していません.これはその位置によって決まります.だからLuaは独立したアプリケーションを開発する言語としては向いていない.しかし、Luaは数学演算や文字列処理などの基本的な機能を備えている.
Luaの現在の最新バージョンは5.1です.
Luaにはデータ型が1つしかない実はhashテーブルです.これを使って配列、チェーンテーブルなどをシミュレートします.文法上、Luaは次の形式をサポートしています.
   data = {} --    table
   data.i = 1
   data.name = "jason"
   data.package = {1,2,2,3,56,7}
   data.others = {}
   data.others.a = 1
   data.others.b = 1.1

これによりLuaはCのstructと同様の形式を持ち,C関数のパラメータを設計するのに非常に便利であり,table 1つで複雑なパラメータを伝達することができる.
2.データ交換の紹介
  • LuaとCプログラムは1つのスタックを通じてデータを交換します:struct lua_State
  • スタックのシーケンス番号は、スタックトップおよびスタックボトムからカウントすることができ、スタックボトムからカウントすると、スタックボトムは1であり、スタックトップ方向にインクリメントされる.スタックトップからカウントすると、スタックトップは-1であり、スタックボトム方向に減少する.スタックトップからカウントする方法が一般的です.スタックのデフォルトサイズは20で、lua_を使用できます.checkstack修正lua_でgettopはスタック内の要素の数を得ることができます.スタックの上に整形要素があるわけではありません.スタックの上部要素のスタック内の正indexを計算し、要素の数に相当します.
  • Lua呼び出しC関数用のスタックは一時的であり,呼び出しが終了すると破棄される.
  • スタックからLuaスクリプトのパラメータを取得する方法
  • Luaスクリプトのグローバル変数の名前を知っていればvoid lua_getglobal (lua_State *L, const char *name) .この関数は、nameが指すLua変数の値をスタックの上に置く.
  • C関数でLua呼び出し関数を取得するために使用されるパラメータの場合:
  • まずlua_gettopチェックパラメータ数
  • 用lua_is...クラス関数検出パラメータのタイプ、エラー処理
  • を行う
  • 用lua_to...クラス関数はパラメータをnumberまたはstringに変換する.(Luaにとって、この2つの単純なタイプしかありません)lua_tonumberはdouble luaを返します.tostringはchar*
  • を返します
  • 用lua_removeスタックから要素
  • を削除
  • は、次の要素の取得を継続する.毎回lua_を呼び出すのでremove、だからlua_を呼び出すたびにtonumberでは、使用するindexはすべて-1、すなわちスタックトップに固定されます.
  • lua_istableが成立すると、スタックの頂上がtableであることを示します.注意tableは取り出せないので、tableの要素を一つ一つ取り出すしかありません.まず要素の名前をスタックの上部に押し込みます:lua_pushstring(L,"i"); そしてlua_gettable呼び出し、値はスタックの上部に配置されます.同時に先ほど押し込んだ要素の名前がポップアップされます.上の方法で、この値を取り出すことができます.覚えてるはずlua_remove. tableのいずれかの要素もtableであれば、繰り返してください.tableのすべての要素が取り終わったら、このtable自体がスタックにあることを覚えておいてください.lua_を使います.removeはそれを削除します.
  • 取得する配列(配列とは、keyが1から始まる数値シーケンスのtableであり、値タイプが同じ)であればlua_nextはこの配列を遍歴することができます:まずlua_pushnil、空の値を押し込み、
     while (lua_next(L, -2) != 0)
    {
        if(lua_isnumber(L,-1)) //      ,    string
        {
             arrf.add((float)lua_tonumber(L, -1));//      
    
             lua_remove(L,-1);
         }
    }
    lua_remove(L,-1);//  NIL

  • CからLuaスクリプト用luaにデータを返す方法push...クラス関数はスタックにデータを圧入し、return nを使用します.Luaがいくつかの戻り値を返したことを伝えに来ました.Luaは,x,y=Test()のような複数の戻り値を生まれつきサポートしている.Luaはnに基づいてスタックから対応するデータを取ります.table:
         lua_newtable(L);//      ,    
    
         lua_pushstring(L, "mydata");//  key
         lua_pushnumber(L,66);//  value
         lua_settable(L,-3);//  key,value,    table   
    
         lua_pushstring(L, "subdata");//  key
         lua_newtable(L);//  value,    table
         lua_pushstring(L, "mydata");//  subtable key
         lua_pushnumber(L,53);//value
         lua_settable(L,-3);//  key,value,    subtable
         lua_settable(L,-3);//    table     -3,  key,value(subtable),    table  
    
        
         lua_pushstring(L, "mydata2");//  
         lua_pushnumber(L,77);
         lua_settable(L,-3);
    
         return 1;//        table.       。
    配列を返す場合は、以下のコードを使用します:(trickに関する注釈に注意して、私は公式の解釈を待っています.検証の結果、この問題はwindowsバージョンでdllのメソッドを呼び出すときにのみ発生します.WinCEは正常です)
         lua_pushstring(L,"arri");
         lua_newtable(L);
         {
            //a trick:otherwise the lua engine will crash. This element is invisible in Lua script
            lua_pushnumber(L,-1);
            lua_rawseti(L,-2,0);
            for(int i = 0; i < arri.size();i++)
            {
                lua_pushnumber(L,arri[i]);
                lua_rawseti(L,-2,i+1);
            }
         }
         lua_settable(L,-3);
    のように生成された配列はLuaの中で以下のように遍歴することができます:
         for i,v in ipairs(data.arri) do
            print(v)
         end
    あるいは
         for i=1,table.getn(data.arri) do
            print(data.arri[i])
         end
    配列しかできません.name、value構成のRecordはできません、table.getnも配列にのみ有効です.
  • は、上記のコードの高度な類似性のため、これらのコードの自動生成を容易に実現することができる.例えば、Cのstruct定義によれば、
    typedef enum 
    {
        BR_9600,
        BR_4800,
    } BaudRate;
    
    typedef struct flag
    {
        int onoff;
        int j;
        long l;
        double d;
        char* name;
        BaudRate rate;
    }flag;
    
    
    は、
    bool DataToLua(flag data,lua_State *L)
    {
        lua_newtable(L);
        lua_pushstring(L,"onoff");
        lua_pushnumber(L,(double)data.onoff);
        lua_settable(L,-3);
        lua_pushstring(L,"j");
        lua_pushnumber(L,(double)data.j);
        lua_settable(L,-3);
        lua_pushstring(L,"l");
        lua_pushnumber(L,(double)data.l);
        lua_settable(L,-3);
        lua_pushstring(L,"d");
        lua_pushnumber(L,(double)data.d);
        lua_settable(L,-3);
        lua_pushstring(L,"name");
        lua_pushstring(L,data.name.c_str());
        lua_settable(L,-3);
        lua_pushstring(L,"rate");
        lua_pushnumber(L,(double)(int)data.rate);
        lua_settable(L,-3);
        return true;
    }
    LuaToDataも同様のコードを自動的に生成することができる.オブジェクト向けにflagをカプセル化し、DataToLuaをflagクラスにする方法を使えば、より便利になります.

  • 3.CとLuaスクリプトの相互呼び出し例
    まず、CのメインプログラムがLuaスクリプトエンジンを初期化し、スクリプトで呼び出すためにいくつかの関数を登録します.
    //function for Lua to call
    //return a integer array to the script
    static int l_getarr (lua_State *L) 
    {
        lua_newtable(L);//create table
        lua_pushnumber(L,1);//push the value
        lua_rawseti(L,-2,1);//set t[1]=v
        lua_pushnumber(L,2);    
        lua_rawseti(L,-2,2);
        lua_pushnumber(L,3);    
        lua_rawseti(L,-2,3);
        lua_pushnumber(L,4);    
        lua_rawseti(L,-2,4);   
        return 1;
    }
    
    int main()
    {
        lua_State *L = lua_open();   /* opens Lua */
        luaopen_base(L);             /* opens the basic library */
        luaopen_table(L);            /* opens the table library */
        
        luaopen_string(L);           /* opens the string lib. */
        luaopen_math(L);             /* opens the math lib. */
        
        lua_pushcfunction(L, l_getarr); // Register a function
        lua_setglobal(L, "getarr");
    
        if (lua_dofile(L, "testlua.lua"))//Load the script file and Run it
        {
            printf("run script failed/n");
        }
        else
        {
            lua_getglobal(L, "result"); //Get the global variant in Lua script
            if(lua_isnumber(L,-1))
            {
                printf("The result of the Lua script is %d/n",lua_tonumber(L,-1));
            }
        }
           
        lua_close(L);
         
        return 0;
    
    }

    スクリプトのコードは次のとおりです.
    array = getarr()
    if array ~= nil then
        result = 1
        for i=1,table.getn(array),1 do
            print(array[i])
        end
    else
        result = 0
    end
    

    4.参考資料
  • http://www.lua.org