OCとLua呼び出しのインタラクション(サードパーティライブラリを使用しない)

8818 ワード

この物の起因を研究する
ゲームのシナリオとして使うわけではありません.luaでオリジナルコントロールを呼び出してプラットフォーム間で実現するためではありません.ただ、当社のAndroid側のキーアルゴリズムの一部と一致するように、このコードをluaに書きました.
最初に資料を調べると、wax、cococos 2 dなどの内容がありますが、私たちはこのような「ヘビー級」のものが必要で、luaファイルが1つなので、最後にCとluaでやり取りして、自分で書くことにしました.
現在、この部分はオンラインで1年+走っていますが、少なくとも使えます.
一部のキーコードと最初の開発構想を共有します.
目標を達成する
1.正確な情報伝達
  • 基礎データフォーマット:BOOL、Number、NSString
  • NSArray、NSDictonaryなどの複雑なパラメータが
  • に伝達される.
    2.リターンデータの実装
  • 基礎データフォーマット:BOOL、Number、NSString
  • NSArray、NSDictonaryなどの複雑なパラメータの戻り値
  • Luaの追加
    Luaをダウンロードし、srcディレクトリをluaに改名し、プロジェクトにドラッグします.luaを削除cとluac.c
    この時点でコンパイルは成功した.
    私が使っているバージョンはLua 5.1です.4,当初はアンドロイドチームのサードパーティjarパッケージバージョンと一致するようにしていた.新しいバージョンでは、文法にいくつかの変更があるはずです.
    Luaの役に立つもの
    これは私がluaのtableをデバッグするためのprintです.タイムスタンプを使うので、数字を判断したところがあります.luaのprintはtableを出力できないフォーマットですが、NSLogよりずっと不便です.そこでネット上で资料を探して、最后に私达の自分の需要に対応して少し调整して、元のホームページはすでに探し出せなくて、参考のリンクの中に置くことができませんでした.
    tab = "    "
    
    dateOutput = true
    
    function print_r(t)
        print_table(t, 0)
    end
    
    function print_table(t, i)
        local indent ="" -- i  ,      
        for j = 0, i do
            indent = indent .. tab
        end
        for k, v in pairs(t) do
            if (type(v) == "table") then -- type(v)       table    ,     ,
                    local key = ""
                    if type(k) ~= "number" then
                        key = k
                        end
                print(indent ..key, "{")
                print_table(v, i + 1) --     
                print(indent .. "}")
            else --          
                if (dateOutput and type(v) == "number" and v > 100000) then
                    v = os.date("%x", v)
                end
                if type(v)=="boolean" then
                    v=(v and "true") or "false"
                end
                print(indent  .. k .. "=" .. v..",")
            end
        end
    end
    

    Luaテストファイル
  • 簡単なテスト、lua端でprintが物を出すことに成功しました
  • function test()
        print("   !")
    end
    
  • luaへの値伝達
  • function simpleParam(value)
        print(value)
    end
    
  • luaから値
  • を取る
    function simpleParam()
        return 5,9
    end
    
  • luaにNSArrayまたはNSDictionarys
  • を伝える.
    function complexParam(value)
        print_r(value)
    end
    
  • luaから値
  • を取る
    function complexParam()
        local s1 = {name = "a", age = 20}
        local s2 = {name = "b", age = 19}
        return {s1, s2}
    end
    

    OC生成Luaのstate
    state = luaL_newstate();
    luaL_openlibs(state);
    lua_settop(state, 0);
    
    NSString *luaFilePath = [[NSBundle mainBundle] pathForResource:@"file" ofType:@"lua"];
    NSString *luaContent = [NSString stringWithContentsOfFile:luaFilePath
                                                     encoding:NSUTF8StringEncoding
                                                        error:nil];
    
    int err;
    if (luaContent == nil || [luaContent isEqualToString: @""]) {
        NSLog(@"Lua_State initial fail,lua file is nil");
    }else {
        err = luaL_loadstring(state, [luaContent cStringUsingEncoding: NSUTF8StringEncoding]);
        if (0 != err) {
            luaL_error(state, "cannot compile the lua file: %s",
                       lua_tostring(state, -1));
            return;
        }
        
        err = lua_pcall(state, 0, 0, 0);
        if (0 != err) {
            luaL_error(state, "cannot run the lua file: %s",
                       lua_tostring(state, -1));
            return;
        }
        
        NSLog(@"Lua_state initial success");
    }
    

    OC呼び出し
  • 簡単なテスト、lua端でprintが物を出すことに成功しました
  • lua_State* state = [[LuaBinding shareBinding] state];
    lua_getglobal(state,"test");
    lua_pcall(state, 0, 0, 0);
    
  • luaへの値伝達
  • lua_State* state = [[LuaBinding shareBinding] state];
    lua_getglobal(state,"simpleParam");
    lua_pushnumber(state, 7);
    lua_pcall(state, 1, 0, 0);
    
  • luaから値
  • を取る
    lua_State* state = [[LuaBinding shareBinding] state];
    lua_getglobal(state,"simpleParam");
    lua_pcall(state, 0, 2, 0);
    NSInteger result1 = (NSInteger)lua_tointeger(state, -1);
    lua_pop(state, 1);
    NSInteger result2 = (NSInteger)lua_tointeger(state, -1);
    lua_pop(state, 1);
    NSLog(@"%ld,%ld", (long)result1,(long)result2);
    
  • luaにNSArrayまたはNSDictionarysを伝えるここには直接使えるluaはありません.pushXXXXのものを使って、私の今の処理方式は自分でタイプを判断するので、した后にpushNumber、pushStringなどをします.jarバッグの向こうはluaのuserdataとかを使っているそうですが、私は研究していません.開発需要が急いでいたので、luaにはあまり興味がありませんでした.私はuserdataを持っていませんが、最近のテストでは、1外3 Mのデータファイルを転送して処理しました.私たちは0.1 sしか使いませんでしたが、アンドロイドのサードパーティライブラリは10 s使いました.私が唯一心配しているのは、メモリというものです.確かにCとluaに詳しくないからです.
    コードリファレンス
    - (void)pushObject:(id)object state:(lua_State *)state{
        unsigned int outCount = (unsigned int)[object count];
        
        if ([object isKindOfClass:[NSDictionary class]]) {
            lua_createtable(state, outCount, 0);
            for (NSString* key in object) {
                id value = object[key];
                
                lua_pushstring(state, [key cStringUsingEncoding: NSUTF8StringEncoding]);
                if ([value isKindOfClass: [NSString class]]) {
                    lua_pushstring(state, [value cStringUsingEncoding: NSUTF8StringEncoding]);
                } else if([value isKindOfClass: [NSNumber class]]) {
                    lua_pushnumber(state, [value doubleValue]);
                } else {
                    [self pushObject:value state:state];
                }
                
                lua_rawset(state, -3);
            }
        } else {
            lua_createtable(state, outCount, 0);
            for (int i = 0; i < outCount; i++) {
                lua_pushinteger(state, i + 1);
                
                id element = object[i];
                if ([element isKindOfClass: [NSString class]]) {
                    lua_pushstring(state, [element cStringUsingEncoding: NSUTF8StringEncoding]);
                } else if([element isKindOfClass: [NSNumber class]]) {
                    lua_pushnumber(state, [element doubleValue]);
                } else {
                    [self pushObject:element state:state];
                }
                
                lua_settable(state, -3);
            }
        }
    }
    
  • luaからNSArrayまたはNSDictionarysを取る第4条と同様に、既成のlua_toXXXXが利用可能です.

  • リファレンスコード
    - (id)readLuaTable:(lua_State *)state{
        int index = lua_gettop(state);
        lua_pushnil(state);
        
        id info = nil;
        while(lua_next(state, index) != 0)
        {
            if (info == nil) {
                if (lua_type(state, -2) == LUA_TNUMBER) {
                    info = [NSMutableArray array];
                }else {
                    info = [NSMutableDictionary dictionary];
                }
            }
            
            if(lua_isnumber(state, -1)){
                double value = lua_tonumber(state, -1);
                if ([info isKindOfClass: [NSMutableDictionary class]]) {
                    [info setObject: @(value)
                             forKey: [NSString stringWithUTF8String: lua_tostring(state, -2)]];
                }else if ([info isKindOfClass: [NSMutableArray class]]) {
                    [info addObject: @(value)];
                }
            }
            else if(lua_isstring(state, -1)){
                const char* value = lua_tostring(state, -1);
                if ([info isKindOfClass: [NSMutableDictionary class]]) {
                    [info setObject: [NSString stringWithUTF8String: value]
                             forKey: [NSString stringWithUTF8String: lua_tostring(state, -2)]];
                }else if ([info isKindOfClass: [NSMutableArray class]]) {
                    [info addObject: [NSString stringWithUTF8String: value]];
                }
            }
            else if(lua_isboolean(state, -1)){
                BOOL value = lua_toboolean(state, -1);
                if ([info isKindOfClass: [NSMutableDictionary class]]) {
                    [info setObject: @(value)
                             forKey: [NSString stringWithUTF8String: lua_tostring(state, -2)]];
                }else if ([info isKindOfClass: [NSMutableArray class]]) {
                    [info addObject: @(value)];
                }
            }
            else if(lua_istable(state, -1)){
                id value = [self readLuaTable: state];
                if (value != nil && [info isKindOfClass: [NSMutableDictionary class]]) {
                    [info setObject: value
                             forKey: [NSString stringWithUTF8String: lua_tostring(state, -2)]];
                }else if (value != nil && [info isKindOfClass: [NSMutableArray class]]) {
                    [info addObject: value];
                }
            }else {
                NSLog(@"   lua   ");
            }
            
            lua_pop(state, 1);
        }
        return info;
    }
    

    リファレンス
    http://blog.stokedsoftware.com/blog/2012/02/04/scripting-ios-games-with-lua/