tolua集成lua-protobuf庫

在tolua基礎上,爲了方便使用proto3,這裏集成了lua-protobuf庫!
十分感謝兩位開源庫的大大,tolua的蒙大和lua-protobuf的Xavier!在兩位的github上有q羣的聯繫方式,歡迎加羣交流!
有什麼問題也可以在我blog下留言!
本文基於win7x64,unity2017.4,tolua當前最新版本,tolua_runtime當前最新版本,lua-protobuf當前最新版本編寫

一丶編譯tolua庫

資源下載:
tolua_runtime
https://github.com/topameng/tolua_runtime
NDK 版本:android-ndk-r10e 默認安裝到 D:/android-ndk-r10e
https://dl.google.com/android/repository/android-ndk-r10e-windows-x86_64.zip
配置好的Msys2下載
https://pan.baidu.com/s/1c2JzvDQ
lua-protobuf
https://github.com/starwing/lua-protobuf

正文:
1.將lua-protobuf工程中的pb.c和pb.h拷貝到tolua_runtime根目錄,覆蓋pb.c
編譯各平臺dll
https://www.jianshu.com/p/5a35602adef8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
2.編譯後tolua_runtime下的Plugins文件夾拷貝至tolua文件夾下同名覆蓋

問題:
1.NDK路徑問題
在tolua_runtime中
build_arm.sh
build_arm64.sh
build_x86.sh
link_arm64.bat
中ndk路徑需要和你電腦上ndk的目錄一致!
2.羣友的總結
(感謝 lua-protobuf交流羣 - 潛水的小懶貓 麼麼噠!)
a.在mac上替換tolua.bundle文件時,需要重啓unity,不然無法讀取pb
b.在編譯mac時,會提示i386架構被棄用,需刪掉,將不再支持iPhone5以下機型
(如果執行build_osx.sh時提示不在支持32位,請打開macnojit 在build Setting移除i386的支持即可)
c.在發佈ios時,要刪除tolua目錄下的pb.c文件,不然編譯不通過
d.如果執行.sh提示權限不足 可以在終端執行:chmod 777 tolua根目錄 然後再次執行.sh腳本即可
3.編譯工具的一些說明
Msys2下載後,在其根目錄有mingw32_shell.bat和mingw64_shell.bat用來分別開啓32位和64位 Msys
32位用於執行tolua_runtime中的build_arm.sh、build_win32.sh、build_x86.sh
64位用於執行tolua_runtime中的build_arm64.sh、build_win64.sh
build_ios.sh、build_osx.sh需要在mac 下執行
build_ubuntu.sh需要在linux下執行(不使用linux開發,不要要編譯)
4…sh怎麼執行?
在各終端(PC用Msys,mac和linux都是自帶)進入.sh腳本所在目錄 ./xxx.sh
在這裏插入圖片描述
5.各種.sh執行中的Error
一定要注意,有錯誤就要修改,要不打出的dll不保證好用!Error的種類有很多,可以參見出錯時的日誌,大部分都是配置的問題,要是C庫有問題,及時聯繫對應庫的作者,驗證是否爲bug!

二丶tolua接入(編寫測試Demo)
資源下載:
tolua
https://github.com/topameng/tolua

正文:
1.將lua-protobuf中的protoc.lua、luaunit.lua和serpent.lua拷貝至tolua工程Assets\ToLua\Lua(tolua自帶lua)文件夾下或者Assets\Lua(自己的業務lua)下
2.unity打開tolua工程,在LuaDLL.cs public static extern int luaopen_pb(IntPtr L);這行下添加

		// lua-protobuf >>>>>>>
        [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern int luaopen_pb_io(IntPtr L);

        [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern int luaopen_pb_conv(IntPtr L);

        [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern int luaopen_pb_buffer(IntPtr L);

        [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern int luaopen_pb_slice(IntPtr L);
        // lua-protobuf <<<<<<

3.在Assets\ToLua\Examples\TestLuaProtobuf新建測試目錄,在該目錄下新建測試場景TestLuaProtobuf,新建測試腳本TestLuaProtobuf.cs掛於MainCamera下
TestLuaProtobuf.cs腳本如下

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using LuaInterface;
using System;

public class TestLuaProtobuf : MonoBehaviour {
    //lua-protobuf 測試用lua腳本
    string script =
        @"
            local pb = require 'pb'
            local protoc = require 'protoc'

            -- load schema from text
            assert(protoc:load[[
               message Phone {
                    optional string name = 1;
                    optional int64  phonenumber = 2;
                }
                message Person
                {
                    optional string name = 1;
                optional int32  age      = 2;
                  optional string address = 3;
                repeated Phone  contacts = 4;
               } ]])

            -- lua table data
            local data = {
               name = 'ilse',
               age  = 18,
               contacts = {
                  { name = 'alice', phonenumber = 12312341234 },
                  { name = 'bob',   phonenumber = 45645674567 }
               }
            }

            -- encode lua table data into binary format in lua string and return
            local bytes = assert(pb.encode('Person', data))
            print(pb.tohex(bytes))

            -- and decode the binary data back into lua table
            local data2 = assert(pb.decode('Person', bytes))
            print(require 'serpent'.block(data2))
        ";

    int bundleCount = int.MaxValue;
    string tips = null;
    LuaState luaState = null;

    bool testAB = false;//是否打包AB加載

    void Start()
    {
#if UNITY_5 || UNITY_2017 || UNITY_2018
        Application.logMessageReceived += ShowTips;
#else
        Application.RegisterLogCallback(ShowTips);
#endif
        if (!testAB) 
        {
            OnBundleLoad();
            return;
        }
        LuaFileUtils file = new LuaFileUtils();
        file.beZip = true;
#if UNITY_ANDROID && UNITY_EDITOR
        if (IntPtr.Size == 8)
        {
            throw new Exception("can't run this in unity5.x process for 64 bits, switch to pc platform, or run it in android mobile");
        }
#endif
        StartCoroutine(LoadBundles());
    }

    void OnBundleLoad()
    {
        luaState = new LuaState();
        luaState.Start();
        OpenLuaProtobuf();
        luaState.DoString(script);
        luaState.Dispose();
        luaState = null;

    }
    /// <summary>
    /// 這裏tolua在OpenLibs的時候並不一定會註冊,這裏註冊一下
    /// </summary>
    void OpenLuaProtobuf()
    {
        luaState.LuaGetField(LuaIndexes.LUA_REGISTRYINDEX, "_LOADED");
        luaState.OpenLibs(LuaDLL.luaopen_pb);
        luaState.LuaSetField(-2, "pb");

        luaState.OpenLibs(LuaDLL.luaopen_pb_io);
        luaState.LuaSetField(-2, "pb.io");

        luaState.OpenLibs(LuaDLL.luaopen_pb_conv);
        luaState.LuaSetField(-2, "pb.conv");

        luaState.OpenLibs(LuaDLL.luaopen_pb_buffer);
        luaState.LuaSetField(-2, "pb.buffer");

        luaState.OpenLibs(LuaDLL.luaopen_pb_slice);
        luaState.LuaSetField(-2, "pb.slice");
    }

    void ShowTips(string msg, string stackTrace, LogType type)
    {
        tips += msg;
        tips += "\r\n";
    }

    void OnGUI()
    {
        GUI.Label(new Rect(Screen.width / 2 - 200, Screen.height / 2 - 150, 400, 300), tips);
    }

    void OnApplicationQuit()
    {
#if UNITY_5 || UNITY_2017 || UNITY_2018
        Application.logMessageReceived -= ShowTips;
#else
        Application.RegisterLogCallback(null);
#endif
    }

    IEnumerator CoLoadBundle(string name, string path)
    {
        using (WWW www = new WWW(path))
        {
            if (www == null)
            {
                Debugger.LogError(name + " bundle not exists");
                yield break;
            }

            yield return www;

            if (www.error != null)
            {
                Debugger.LogError(string.Format("Read {0} failed: {1}", path, www.error));
                yield break;
            }

            --bundleCount;
            LuaFileUtils.Instance.AddSearchBundle(name, www.assetBundle);
            www.Dispose();
        }
    }

    IEnumerator LoadFinished()
    {
        while (bundleCount > 0)
        {
            yield return null;
        }

        OnBundleLoad();
    }

    public IEnumerator LoadBundles()
    {
        string streamingPath = Application.streamingAssetsPath.Replace('\\', '/');

#if UNITY_5 || UNITY_2017 || UNITY_2018
#if UNITY_ANDROID && !UNITY_EDITOR
        string main = streamingPath + "/" + LuaConst.osDir + "/" + LuaConst.osDir;
#else
        string main = "file:///" + streamingPath + "/" + LuaConst.osDir + "/" + LuaConst.osDir;
#endif
        WWW www = new WWW(main);
        yield return www;

        AssetBundleManifest manifest = (AssetBundleManifest)www.assetBundle.LoadAsset("AssetBundleManifest");
        List<string> list = new List<string>(manifest.GetAllAssetBundles());
#else
        //此處應該配表獲取
        List<string> list = new List<string>() { "lua.unity3d", "lua_cjson.unity3d", "lua_system.unity3d", "lua_unityengine.unity3d", "lua_protobuf.unity3d", "lua_misc.unity3d", "lua_socket.unity3d", "lua_system_reflection.unity3d" };
#endif
        bundleCount = list.Count;

        for (int i = 0; i < list.Count; i++)
        {
            string str = list[i];

#if UNITY_ANDROID && !UNITY_EDITOR
            string path = streamingPath + "/" + LuaConst.osDir + "/" + str;
#else
            string path = "file:///" + streamingPath + "/" + LuaConst.osDir + "/" + str;
#endif
            string name = Path.GetFileNameWithoutExtension(str);
            StartCoroutine(CoLoadBundle(name, path));
        }

        yield return StartCoroutine(LoadFinished());
    }
}

4.各平臺測試
pc上
TestLuaProtobuf.cs 腳本中testAB = false,直接運行測試場景TestLuaProtobuf即可,正常輸出
在這裏插入圖片描述
移動端
TestLuaProtobuf.cs 腳本中testAB = true
unity切換至對應平臺,例如切換至Android,執行untiy菜單欄 Lua/Build bundle files no jit,等待打包執行完畢,分別在Assets\StreamingAssets下生成對應平臺lua AB包,Android、iOS
在這裏插入圖片描述
在這裏插入圖片描述
添加測試場景,build 安裝包即可!
安卓正常結果
在這裏插入圖片描述
問題:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章