在ios android裝置上使用 Protobuf (使用dll方式)
如果你的工程可以以.Net 2.0 subset模式執行,請看這個帖子中的方法。
如果只能以.Net 2.0下執行,就可以繼續往下看了。
=============================================================
protobuf是google定製的一個協議,可以方便地進行資料的序列化和反序列操作。(支援多個平臺間通訊)
可以用它來進行資料的本地快取
以及 網路協議的傳輸 等等。
要了解protobuf協議看下面兩個網址:
Unity有兩個Protobuf庫可以用分別是 protobuf-csharp-port, protobuf-net
兩個庫使用都可以在android上執行正常,但是在ios上面會出現下面的異常:
ExecutionEngineException:
Attempting to JIT compile method
JIT意思就是執行時編譯,而ios上是aot (full)編譯,因此任何庫只要使用jit方式都無法在ios上執行。
要了解jit以及aot,請看下面的網址:
經過嘗試之後,可以用protobuf-net的預編譯來在ios以及android裝置上執行
接下來按步驟講解,最後會附上測試工程。
一、 下載protobuf-net 及配置
下載之後解壓到你的硬碟的某個目錄 , 最好是將 Precompile\precompile.exe
我們還需要CoreOnly\ios中的三個檔案,之後會用到,而且最終會放到unity工程下。
二、生成cs程式碼
使用protogen 命令列來生成程式碼 (precompile以及protogen都只能在windows下執行,在mac上可能可以通過mono來執行這個exe,但是沒有試過。)
使用例子如下:
protogen -i:Test1.proto -i:Test2.proto -i:Test3.proto -o:Output.cs -ns:com.fbmly.model
-i 是輸入檔案,可以有多個
-o 輸出的cs檔案, 只能有一個..如果-i有多個 會將所有的程式碼生成到這一個cs檔案當中
-ns 名稱空間 最好使用,如果不使用每次生成的預設名稱空間是proto的檔名。
通常來說 只要把所有的資料結構生成到一個cs就行了(要不然使用多個-i , 要不就把所有protobuf定義寫在一個proto檔案中),這樣之後之後操作比較方便一些。
經過這一步你就得到了生成之後的cs檔案。
三、編譯dll庫
使用MonoDevelop工具 將上一步生成的cs檔案編譯成dll庫.
1.建立一個新的工程 (File->New->Solution)
2.在彈出的對話方塊中選擇 C# 再選擇 Library.
3.在下方填寫好工程的名字 (這個名字是生成dll的名字,所以要起好)
4.點選forward (之後還要點一次ok)
5.刪掉預設生成的MyClass.cs檔案,有必要的話在AssemblyInfo.cs裡填寫一些版權資訊。
6.將上一步用protogen生成的cs檔案 加入到工程 (在左邊工程名 上右鍵 就可以新增)
7.新增protobuf-net引用庫
點選工程的References->Edit References
然後選擇剛才的CoreOnly\ios下的dll庫 , 雙擊庫檔案就可以加到右邊
最後檢查下References裡面如果有protobuf-net.dll就正確了。
8.都做好後, 點選Build->Build All就可以在當前工程生成dll了
不要忘記 debug 和 release的選擇 ,測試完後應該重新拿release再編譯一次的。
9. 左下角提示成功 就 會在當前工程目錄下生成dll檔案了 (我這裡是 TestModel.dll)
這個dll存放的是你所有的資料結構。
四、預編譯序列化庫
上一步生成了資料的dll檔案,這一步需要用到上一步的dll檔案來生成專門序列化的dll檔案。
首先要保證TestModel.dll和編譯時所使用的庫在同一目錄 ( 上一步生成的dll檔案目錄,會自動把protobuf-net庫檔案也複製過來 , 所以只需要記住這一點就行了。 比如你要是複製到其他目錄進行操作, 這點會很重要 )
然後開啟命令列, 定位到dll工程目錄下的bin\Debug 或 bin\Release目錄
然後執行以下命令(修改成你所設定的名字):
precompile TestModel.dll -o:ProtobufSerializer.dll -t:com.fbmly.ProtobufSerializer
TestModel.dll就是上一步生成的dll檔案,-o是生成的檔名 -t是在ProtobufSerialize.dll中所生成的序列化類的類名 支援名稱空間,不用名稱空間就直接寫類名就可以了。
如果最後有 All Done 提示, 就代表生成成功了。
複製程式碼
1 2 3 4 5 6 7 8 9 10 |
D:\protobuf-net\Precompile\Model>precompile
TestModel.dll -o:ProtobufSerializer.
dll
-t:com.fbmly.ProtobufSerializer
protobuf-net
pre-compiler
Detected
framework: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
Resolved
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll
Resolved
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll
Resolved
protobuf-net.dll
Adding
Fbmly1.Fbmly...
Compiling
com.fbmly.ProtobufSerializer to ProtobufSerializer.dll...
All done
|
五、在unity中測試
將第三步和第四步中生成的 TestModel.dll ,ProtobufSerializer.dll 以及參與編譯的protobuf-net庫 複製到unity的工程中去。
現在可以開始測試了
測試程式碼:
複製程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
void OnGUI(
)
{
if (
GUILayout.Button ( "Test" ,
GUILayout.Width ( 200f ) , GUILayout.Height ( 200f ) ) )
{
Fbmly
data = new Fbmly
( );
data.mmm
= 10;
ProtobufSerializer
serializer = new ProtobufSerializer
( );
//Serialize
byte []
buffer = null ;
using (
MemoryStream m = new MemoryStream
( ) )
{
serializer.Serialize
( m , data );
m.Position
= 0;
int length
= ( int )m.Length;
buffer
= new byte [length];
m.Read(buffer,
0 ,length);
}
Fbmly
newData = null ;
//Deserialize
using (
MemoryStream m = new MemoryStream
( buffer ) )
{
newData
= serializer.Deserialize ( m , null , typeof (
Fbmly ) ) as Fbmly;
}
Debug.Log
( "newData.mmm=" +
newData.mmm );
}
}
|
測試工程已經在touch4上測試通過,並且工程設定為.Net 2.0 Subset
如果各位在真機上出現錯誤,不妨設定到.Net 2.0試試。
這種方式已經在遊戲專案中驗證過了,複雜的資料也是沒有問題的(遊戲專案用了500多個proto定義) , ios和android都可用。
最後附上工程包:裡面附了一個工具類,可以序列化的時候使用, 用的時候只需要修改一下就可以了,因為裡面維護了一個序列化類的單例。