Erlang使用ProtoBuffer


最近有工作需要打算為項目服務器做一個機器人,測試測試壓力,根據自己的經驗,使用Erlang來做是最合適不過的了,但是服務器使用的C++語言,使用了Google的ProtoBuffer作為協議進行數據交換,而Erlang並沒有官方的Protobuffer版本支持,官方僅支持C++,JAVA,Python等幾種比較主流的語言。在網上搜索了一下,ProtoBuffer的第三方Erlang版本主要有以下幾個:

  1. https://github.com/ngerakines/erlang_protobuffs/tree/master
  2. https://github.com/basho/erlang_protobuffs
  3. http://piqi.org/
  4. https://github.com/tomas-abrahamsson/gpb

我使用了一下其中的一兩個版本,但是發現有的對import的支持很有限,甚至不支持,而項目中的PB是有用到,最后選定第四個版本gpb,這個版本可以使用項目中的大部分proto文件生成Erlang源文件,僅有import引用的類型有引用前綴的時候不支持。舉個例子:

假如現在有兩個proto文件,A.proto和B.proto,A.proto中定義了一個枚舉:

package A;

enum Type { T_A = 0; T_B = 1; }

 B.proto中引用了這個枚舉:

message M_Test
{
    required A.T_A eType = 1;
    optional int32  other = 2;
}

 這個時候編譯proto文件,會出現如下錯誤:

in msg M_Test, field eType: undefined reference  A.T_A

但是如果將B.proto中的消息定義改為:

message M_Test
{
    required T_A eType = 1;
    optional int32  other = 2;
}

則能夠成功編譯通過。

為了解決這個問題,研究了一下gpb的源碼,在gpb_parse.erl中有一個函數:

%% -> {found, {msg,FullName}|{enum,FullName}} | not_found
resolve_ref(Defs, Ref, Root, FullName) ->
    case is_absolute_ref(Ref) of
        true  ->
            FullRef = ensure_path_prepended(Root, Ref),
            find_typename(FullRef, Defs);
        false ->
            PossibleRoots = compute_roots(FullName),
            find_ref_rootwards(PossibleRoots, Ref, Defs)
    end.

這個函數是專門用來解析引用的,其中的變量Ref在第一種寫法,其值為:['A','.','T_A'],這個時候解析不了;而第二種方式的寫法其值為:['T_A']

如果匹配一下第一種寫法的值,然后將之改為第二種寫法的值,即可正常編譯。為此我加了一個過濾函數如下:

filterRef([_,'.',Type]) -> [Type];
filterRef(Other) -> Other.

 然后把resolve_ref函數改為:

%% -> {found, {msg,FullName}|{enum,FullName}} | not_found
resolve_ref(Defs, Ref0, Root, FullName) ->
    Ref = filterRef(Ref0),
    case is_absolute_ref(Ref) of
        true  ->
            FullRef = ensure_path_prepended(Root, Ref),
            find_typename(FullRef, Defs);
        false ->
            PossibleRoots = compute_roots(FullName),
            find_ref_rootwards(PossibleRoots, Ref, Defs)
    end.

這樣,就可以正常的編譯項目中所有的Proto文件了。

btw,按gpb官方的介紹來看,其支持proto2以及proto3的語法,但不知道是否完全支持,有待驗證。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM