在lua环境中使用protobuf

摘要:
最近,在cocos2dx项目中,您需要在LUA脚本层中使用protobuf协议。所以我开始研究LUA下protobuf的实现,并记录了整个过程,希望能帮助其他人。如果不安装,以后就无法安装python版本的protobuf。注意:如果protoc如果未放置exe,将发生错误,并且无法找到googleprotobufcompler目录。在protoc-gen-lua目录中编写批处理:buildproto-Bat。这是通过在C++中构建lua的protobuf环境来实现的。在Linux中,需要使用protoc-gen-lua/protobuf中的makefile来编译pb。c转化为pb。所以然后调用pb中的条目。c在缅因州。代码如下:locala=package。loadlib(“pb.dll”,“luaope”

最近在cocos2dx的项目中,需要在LUA脚本层使用protobuf协议。官方已经推出了很多种语言的版本。但唯独LUA版本不全。于是开始研究protobuf在LUA下的实现,将完整的过程记录了下来,希望对其它人能有所帮助。

1、下载protoc-gen-lua

可以通过HG从服务器(hg clonehttps://code.google.com/p/protoc-gen-lua/)上下载最新的版本。

简单介绍一下里面的三个目录:

example存放的一个示例协议,

plugin将.proto协议转为LUA脚本需要的工具。要注意,这个工具是用PYTHON写的,所以后面我们需要安装PYTHON。

rotobuf这里存放了工程需要的文件。其中pb.c是C码文件。主要是在工程中引用,也可以编译成动态文件(.so)供LUA调用。其它LUA文件则需要引入到LUA工程中。

2、安装PYTHON27。推荐是这个版本。

3、下载protobuf然后编译出protoc.exe。

可以用SVN从服务器上(http://protobuf.googlecode.com/svn/trunk)下载最新的protobuf。我使用的是protobuf-2.4.1。

进入protobuf-2.4.1/vsprojects利用VS2010进行编译。生成的protoc.exe放到protobuf-2.4.1/src下。如果不放,后面无法安装python版的protobuf。

4、编译python版本的protobuf

在protobuf-2.4.1python下运行python setup.py build,然后再执行python setup.py install。

注意:如果第3步的protoc.exe没有放,会出现错误找不到googleprotobufcompiler目录。

5、制作转换协议的批处理

在protoc-gen-lua/plugin目录下编写批处理:protoc-gen-lua.bat,就下面一行代码。

///////////////////////////////////////////////////////////////////////////////////////

@python "%~dp0protoc-gen-lua"

///////////////////////////////////////////////////////////////////////////////////////

但要确保你的python命令能正常运行。否则将python.exe所在的目录加到环境变量path中。

接着拷贝一份protoc.exe到protoc-gen-lua目录。第3步我们已经编译了出了protoc.exe。在协议转换中,我们需要使用他。

在protoc-gen-lua目录编写批处理:buildproto.bat 来转换协议。

rem 切换到.proto协议所在的目录  
cd ../luascript  
rem 将当前文件夹中的所有协议文件转换为lua文件  
for %%i in (*.proto) do(    
echo %%i  
"..protobufprotocprotoc.exe" --plugin=protoc-gen-lua="..protobufpluginprotoc-gen-lua.bat" --lua_out=. %%i  
)  
echo end  
pause 

请正确指定protoc.exe和protoc-gen-lua.bat相对协议目录的路径。

6、转换协议文件

protoc-gen-lua/example目录中,有一个协议文件person.proto,可以拿他做一下试验,会生成一个person_pb.lua

7、编译pb.c文件

protoc-gen-lua/protobuf目录中有一个pb.c文件。我们需要用他来协助lua完成protobuf的功能。

用vs2010新建一个控制台程序。将pb.c加入到工程中。在windows平台下,要对pb.c做如下修改。

1)将 #include <endian.h>修改为

#ifndef _WIN32
#include <endian.h>
#endif

避免在windows下缺失文件报错.

2)调整struct_unpack函数前几行为

static int struct_unpack(lua_State *L)
{
uint8_t format = luaL_checkinteger(L, 1);
size_t len;
const uint8_t* buffer = (uint8_t*)luaL_checklstring(L, 2, &len);
size_t pos = luaL_checkinteger(L, 3);
uint8_t out[8];

buffer += pos;

3)在主函数前面申明pb.c的入口。

extern "C" { int luaopen_pb (lua_State *L);} // 注意防在命名空间外的全局声明

编写主函数如下:

#include "stdafx.h"  
extern "C"{  
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>  
    int luaopen_pb (lua_State *L);  
}  
int main(int argc, char*argv[])  
{  
    lua_State *L =lua_open();  
    luaL_openlibs(L);  
    luaopen_pb(L);  
    luaL_dofile(L, "main.lua");   
    lua_pcall(L, 0, LUA_MULTRET, 0);  
    lua_close(L);       
    return 0;   
}  

工程需要lua5.1.lib的接入。这个请自行编译。

8、编写main.lua。

也就是测试文件,可以参考protoc-gen-lua/example中的test.lua。

package.path = package.path .. ';./protobuf/?.lua'
require "person_pb"
local msg =person_pb.Person()  
msg.id = 100
msg.name = "foo"
msg.email = "bar"
local pb_data = msg:SerializeToString()  --Parse Example  
print("create:", msg.id, msg.name, msg.email, pb_data)  
local msg =person_pb.Person()   
msg:ParseFromString(pb_data)   
print("parser:", msg.id, msg.name, msg.email, pb_data)  

10、总结。

这里实现了,在C++中搭建lua的protobuf环境。但未实现纯粹的Lua-protobuf环境。

如果需要在LUA中实现protobuf,那需要自己将pb.c编译成dll。在linux下需要利用protoc-gen-lua/protobuf中的makefile将pb.c编译成pb.so。

然后将pb.so或pb.dll导入到lua工程中。然后在main.lua中调用pb.c中的入口,代码如下:

local a = package.loadlib("pb.dll", "luaopen_pb");  
a()

理论上是这样,我还没有做详细的测试。如果有进展,再完善本贴。

转自:http://blog.csdn.net/sunshine7858/article/details/9260671

-----------------------------------------------------------------------------------------------

下载地址:
http://code.google.com/p/protobuf/downloads/list
安装命令
tar -xzf protobuf-2.5.0.tar.gz
cd protobuf-2.5.0
./configure --prefix=$INSTALL_DIR

make

make check

make install

然后进入python目录,

python setup.py install --prefix=$INSTALL_DIR

写proto文件
package lm;
message Person
{
required int32 id = 1;
required string str = 2;
optional int32 opt = 3;
}
保存为 testp.testpb.proto
编译指令
protoc -I=/home/workspace/testprob --python_out=/home/workspace/testprob /home/workspace/testprob/testp.testpb.proto
google
https://developers.google.com/protocol-buffers/docs/pythontutorial
报错
package directory 'google/protobuf/compiler' does not exist
解决
https://groups.google.com/forum/?fromgroups=#!topic/protobuf/YeT5RW4qCxY
python ./setup.py build
sudo python ./setup.py install
报错
File "/home/workspace/testprob/testp/testpb_pb2.py", line 6, in <module>
from google.protobuf import reflection as _reflection
File "build/bdist.linux-i686/egg/google/protobuf/reflection.py", line 68, in <module>
File "build/bdist.linux-i686/egg/google/protobuf/internal/python_message.py"
ImportError: cannot import name enum_type_wrapper
解决
http://code.google.com/p/protobuf/issues/detail?id=438
Log message
Fix issue 438 : add missing 'enum_type_wrapper' to setup.py
是安装包的一个改进文件,copy下来, 重新安装
根据安装目录下的demo 自己改写了个简单的, 觉得它那个还是麻烦
write.py
import testpb_pb4
import sys
p = testpb_pb2.Person()
try:
f = open(sys.argv[1], "rb")
p.ParseFromString(f.read())
f.close()
except IOError:
print sys.argv[1] + ": File not found. Creating a new file."
p.id = 32
p.str = "test"
f = open(sys.argv[1], "wb")
f.write(p.SerializeToString())
f.close()
print "write success"
编译指令 python write.py "test"
read.py
import sys
import testpb_pb2
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
sys.exit(-1)
p = testpb_pb2.Person()
f = open(sys.argv[1], "rb")
p.ParseFromString(f.read())
f.close()
print "p.str = ", p.str
print "p.id=", p.id
编译指令 python read.py "test"

免责声明:文章转载自《在lua环境中使用protobuf》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇linux--日志文件过大?查看日志文件某个时间段的内容转:和机器学习和计算机视觉相关的数学下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python实现 灰色关联分析 与结果可视化

之前在比赛的时候需要用Python实现灰色关联分析,从网上搜了下只有实现两个列之间的,于是我把它改写成了直接想Pandas中的计算工具直接计算person系数那样的形式,可以对整个矩阵进行运算,并给出了可视化效果,效果请见实现 灰色关联分析法 对于两个系统之间的因素,其随时间或不同对象而变化的关联性大小的量度,称为关联度。在系统发展过程中,若两个因素变化的...

Windows之权限的继承性 累加性 优先性 交叉性及四项基本原则

Windows NT以后的文件,及文件夹共享设置有以下特性:继承性、累加性、优先性、交叉性。     继承性是说下级的目录在没有经过重新设置之前,是拥有上一级目录权限设置的。这里还有一种情况要说明一下,在分区内复制目录或文件的时候,复制过去的目录和文件将拥有它现在所处位置的上一级目录权限设置。但在分区内移动目录或文件的时候,移动过去的目录和文件将拥有它原先...

Eclipse开发PHP环境配置

首先准备好软件: 1. Apache,到这里找个最新版本 2. PHP,到这里下载 3. Eclipse IDE for Java EE Developers,到这里下载 4. DLTK Core Frameworks 1.0 Integration build,到这里下载 注意:DLTK是所谓动态语言开发包,PDT依赖于它,不知为什么现在官方主页上的稳定...

Debug与Release的区别

  Debug版本包括调试信息,所以要比Release版本大很多(可能大数百K至数M)。至于是否需要DLL支持,主要看你采用的编译选项。如果是基于ATL的,则Debug和Release版本对DLL的要求差不多。如果采用的编译选项为使用MFC动态库,则需要MFC42D.DLL等库支持,而Release版本需要MFC42.DLL支持。Release  Buil...

python 面向对象

概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。 1 2 3 4 5 6 7 8...

PHP-深入学习Smarty

本文中的边界标签分别为"<{"和"}>" start-12, 都是静态模板中的内容, 即使函数也只是模板中的标签或者变量调解器; 13-end, 都是smarty对象的方法和属性 表达式中不能乱使用空格 1.注释   <{* 我是注释内容 *}> //相当于PHP的注释, 而不是HTML文件的注释, 所以不会出现在页面源码中 2.函...