Erlang使用ProtoBuffer
最近有工作需要打算为项目服务器做一个机器人,测试测试压力,根据自己的经验,使用Erlang来做是最合适不过的了,但是服务器使用的C++语言,使用了Google的ProtoBuffer作为协议进行数据交换,而Erlang并没有官方的Protobuffer版本支持,官方仅支持C++,JAVA,Python等几种比较主流的语言。在网上搜索了一下,ProtoBuffer的第三方Erlang版本主要有以下几个:
- https://github.com/ngerakines/erlang_protobuffs/tree/master
- https://github.com/basho/erlang_protobuffs
- http://piqi.org/
- 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的语法,但不知道是否完全支持,有待验证。
Erlang使用ProtoBuffer的更多相关文章
- thrift与protobuffer的区别
thrift由facebook出品,protobuffer由google出品: 下面对比一下这两个的区别.参考:http://zhidao.baidu.com/link?url=yNLBeHhWokf ...
- [Erlang 0129] Erlang 杂记 VI
把之前阅读资料的时候记下的东西,整理了一下. Adding special-purpose processor support to the Erlang VM P23 简单介绍了Erlang C ...
- [Erlang 0128] Term sharing in Erlang/OTP 下篇
继续昨天的话题,昨天提到io:format对数据共享的间接影响,如果是下面两种情况恐怕更容易成为"坑", 呃,恰好我都遇到过; 如果是测试代码是下面这样,得到的结果会是怎样?猜! ...
- [Erlang 0127] Term sharing in Erlang/OTP 上篇
之前,在 [Erlang 0126] 我们读过的Erlang论文 提到过下面这篇论文: On Preserving Term Sharing in the Erlang Virtual Machine ...
- [Erlang 0126] 我们读过的Erlang论文
我在Erlang Resources 豆瓣小站上发起了一个征集活动 [链接] ,"[征集] 我们读过的Erlang论文",希望大家来参加.发起这样一个活动的目的是因为Erlang相 ...
- [Erlang 0125] Know a little Erlang opcode
Erlang源代码编译为beam文件,代码要经过一系列的过程(见下面的简图),Core Erlang之前已经简单介绍过了Core Erlang,代码转换为Core Erlang,就容易拨开一些语法糖的 ...
- [Erlang 0124] Erlang Unicode 两三事 - 补遗
最近看了Erlang User Conference 2013上patrik分享的BRING UNICODE TO ERLANG!视频,这个分享很好的梳理了Erlang Unicode相关的问题,基本 ...
- [Erlang 0123] Erlang EPMD
epmd进程和Erlang节点进程如影随形,在Rabbitmq集群,Ejabberd集群,Couchbase集群产品文档中都会有相当多的内容讲epmd,epmd是什么呢? epmd 是Erlan ...
- [Erlang 0122] Erlang Resources 2014年1月~6月资讯合集
虽然忙,有些事还是要抽时间做; Erlang Resources 小站 2014年1月~6月资讯合集,方便检索. 小站地址: http://site.douban.com/204209/ ...
随机推荐
- Java EE基础之JSP(二)
接着上篇文章,我们上篇文章讲到了jsp的基本原理以及和servlet的关系,还介绍了jsp的基本语法部分,本篇文章就继续介绍余下的内容. 编译指令Page和include 基本的动作指令 内置对象 一 ...
- HTTP [TCP Retransmission] Continuation or non-HTTP traffic[Packet size limited during capture]
http://www.xianren.org/blog/net/wireshark-q.html 抓到的包数据中常见的错误..待细看,先记下. tcpdump 抓包后发现,出现大量标题字样显示,不利 ...
- 第三方登录 ----QQ登录
学习之前,请大家先看一下oAuth协议. 首先呢,我们进入QQ互联的官方网站 http://connect.qq.com登入我们自己的QQ号,没有QQ号的小伙伴可以忽略本篇博文分享!
- IOS开发创建开发证书及发布App应用(二)——创建证书
2. 创建证书 证书分为两种,一种是开发者证书,主要是用来真机调试的 另一种就是发布证书,就是用来发布应用的, 最好是两种都要下载,不然编译时候可能报错,我猜想可能苹果怕你没用真机调试 创建证书分为两 ...
- 老李分享:android手机测试之适配(1)
Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因.重要概念.解决方案及最佳实践,我相信如果你能认真的学习 ...
- 老李推荐:第2章2节《MonkeyRunner源码剖析》了解你的测试对象: NotePad窗口Activity之NotesList简介
老李推荐:第2章2节<MonkeyRunner源码剖析>了解你的测试对象: NotePad窗口Activity之NotesList简介 NotePad窗口Activity之NotesL ...
- POI 操作Excel疑难点笔记
在POI中,我们可以通过Workbook, Sheet, Row, Cell 对象分别对应Excel文件.工作表.行.单元格. 在POI的使用中,我遇到了几个非常诡异.捉摸不透的问题,现在记录下来. ...
- android中的 Toast 和 AlertDialog
Toast 一般用来显示一些不需要用户操作的提示信息,举个栗子: public void toast(String msg) { //---创建并设置显示的内容和显示时长 Toast toast = ...
- Git版本管理荟萃
用惯了svn,突然转到git难免有点不适,写个笔记好好备忘总结一番. 一.先看历史(imooc上的一个图): 二.git与svn GIT跟SVN一样有自己的集中式版本库或服务器.但,GIT更倾向于被使 ...
- Python:generator的send()方法流程分析
先来一个简单地例子: def foo(): print('starting') while True: r = yield 2 print(r) f = foo() print(f.send(None ...