Lua 中實(shí)現(xiàn) protobuf 序列化,反序列化
https://blog.csdn.net/fanyun7654/article/details/52596000
Protobuf 官方并沒有 Lua版本,然后網(wǎng)易的程序猿開發(fā)出了 protoc-gen-lua ,可以讓我們將 Proto 文件轉(zhuǎn)成 lua 腳本在 Lua中使用,下面是詳細(xì)的編譯、安裝、使用教程。文中用到的代碼、工具都有百度網(wǎng)盤下載。
網(wǎng)盤下載地址: http://pan.baidu.com/s/1bo8Ufd9
1、首先我們需要安裝Python2.7,下載地址:
默認(rèn)安裝到C盤
把安裝目錄添加到環(huán)境變量中,然后打開命令行 控制臺(tái),輸入命令
如果提示 命令不存在,則說明環(huán)境變量沒有設(shè)置正確,如果是如下圖,說明設(shè)置成功 ame.com.cn
2、下載并編譯 Luajit 2.0.4 ,
下載后解壓,找到 LuaJIT-2.0.4/src 目錄,其中有一個(gè)批處理文件 msvcbuild.bat ,這是在 Windows系統(tǒng)的編譯工具。在開始菜單 - 所有應(yīng)用中的 Visual Studio 201x 中找到 Visual Studio Tools,打開 VS201x 開發(fā)人員命令提示,切換到 LuaJIT-2.0.4/src 目錄,執(zhí)行命令
開始編譯 Luajit 2.0.4
像下圖 出現(xiàn) Successfully built LuaJIT for Windows/x86 說明編譯成功

本文轉(zhuǎn)自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
到 LuaJIT-2.0.4\src 目錄中尋找 lua51.dll lua51.lib luajit.exe 這三個(gè)文件是否存在,如果上面編譯成功,那這三個(gè)文件是一定有的。

3、下載并編譯 protobuf-2.4.1
在 protobuf-2.4.1\vsprojects 目錄中打開 protobuf.sln ,如下圖

在 Visual Studio 中將 下圖中 紅框 中的 test 項(xiàng)目 從項(xiàng)目中移除,要來沒用。

刪除后如下圖

項(xiàng)目一個(gè)一個(gè)編譯,不要一起編譯。
首先來編譯 libprotobuf 項(xiàng)目,肯定會(huì)出錯(cuò)。提示如下錯(cuò)誤

原因是Protobuf 中沒有添加對(duì)應(yīng)的頭文件,在項(xiàng)目中 搜索打開 common.h ,添加對(duì)應(yīng)頭文件,如下圖:

再次編譯,就可以編譯成功。
然后編譯 第二個(gè)項(xiàng)目 libprotobuf-lite 。不會(huì)出錯(cuò)。
然后再編譯 第三個(gè)項(xiàng)目 libprotoc 。肯定會(huì)出錯(cuò),如下圖

雙擊定位錯(cuò)誤,或者打開 command_line_interface.cc ,到913行 ,修改為如下圖

再次編譯,即可成功。
最后編譯第四個(gè) 項(xiàng)目 protoc 。編譯成功
然后到 protobuf-2.4.1\vsprojects\Debug 目錄中找到生成的 4 個(gè)文件,如下圖紅框中的文件

這4個(gè)文件會(huì)在 編譯 protoc-gen-lua的時(shí)候用到。
編譯成功后,到 protobuf-2.4.1\Python 文件夾中執(zhí)行命令
4、下載并 編譯安裝 protoc-gen-lua ,
下載解壓后,打開 目錄,如下圖有三個(gè)文件夾

在 plugin 目錄 創(chuàng)建 批處理文件 protoc-gen-lua.bat , 內(nèi)容如下
- @python "%~dp0protoc-gen-lua"
然后將 上一步 編譯 protobuf-2.4.1 中生成的 protoc.exe 拷貝到 protoc-gen-lua-master 目錄,如下圖
然后在 protoc-gen-lua-master 目錄下創(chuàng)建批處理文件 buildproto.bat ,內(nèi)容如下
- rem 切換到.proto協(xié)議所在的目錄
- cd protobuf\luascript
- rem 將當(dāng)前文件夾中的所有協(xié)議文件轉(zhuǎn)換為lua文件
- for %%i in (*.proto) do (
- echo %%i
- "..\..\protoc.exe" --plugin=protoc-gen-lua="..\..\plugin\protoc-gen-lua.bat" --lua_out=. %%i
-
- )
- echo end
- pause
這個(gè)批處理的作用是:先進(jìn)入到一個(gè)文件夾,然后將該文件夾中的 proto 文件 生成 lua 文件。 我這里是進(jìn)入到 protoc-gen-lua-master\protobuf\luascript 。所以我在 protobuf 目錄下新建 目錄 luascript ,在該目錄進(jìn)行 proto 轉(zhuǎn)換 lua 。如果需要在其它目錄進(jìn)行,要把上面批處理的內(nèi)容修改目錄為自己想要的。
好,下面來測(cè)試一下。
在 protoc-gen-lua-master\example 目錄下有一個(gè)測(cè)試的 proto 文件 person.proto ,把它拷貝到 luascript 文件夾。

然后 返回執(zhí)行上面創(chuàng)建的批處理文件 buildproto.bat 。 本文轉(zhuǎn)自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

生成成功,到 luascript 中查看,看到生成了對(duì)應(yīng)的 lua 文件 person_pb.lua 。

5、編寫工程測(cè)試 生成的 protobuf lua 文件
新建一個(gè)空項(xiàng)目,把 protoc-gen-lua-master\protobuf\pb.c 加入到項(xiàng)目中。

在 main.cpp 中添加初始化 Lua 以及初始化 proto-lua 的代碼
- #ifdef _WIN32
- #include<windows.h>
- #endif
-
- 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);
- #ifdef _WIN32
- system("pause");
- #endif
- return 0;
- }
設(shè)置 頭文件引用路徑為 LuaJIT-2.0.4\src 目錄
設(shè)置鏈接器附加庫目錄為 LuaJIT-2.0.4\src 目錄
設(shè)置鏈接器附加依賴項(xiàng)為 lua5.1.4.lib
然后編譯,肯定會(huì)報(bào)錯(cuò)。。如下圖

需要修改 pb.c 的開始部分代碼如下

就是用 宏定義 來判斷,在Windows 系統(tǒng)下不引用 endian.h 這個(gè)文件。
再次編譯,肯定成功。
在上面的代碼中,我們加載了一個(gè) lua 腳本文件 main.lua 。
我們?cè)陧?xiàng)目目錄中新建 main.lua 并添加如下代碼
- package.path = package.path .. ';./protobuf/?.lua;./protobuf/luascript/?.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 msg1 = Person_pb.Person()
- msg1:ParseFromString(pb_data)
- print("parser:", msg1.id, msg1.name, msg1.email, pb_data)
在 lua 代碼里面,我們 測(cè)試了 對(duì) person 的序列化 和 反序列化 。
還記得之前生成的 person_pb.lua 文件嗎?在 protoc-gen-lua-master\protobuf\luascript 目錄里。
我們把整個(gè) protoc-gen-lua-master\protobuf 目錄拷貝到測(cè)試項(xiàng)目 目錄 里來。因?yàn)?main.lua 中要引用這些 lua 文件。

然后運(yùn)行測(cè)試項(xiàng)目

序列化 和 反序列化 測(cè)試成功
測(cè)試工程下載
- http://pan.baidu.com/s/1ntvlBp3
至此, protoc-gen-lua 編譯 測(cè)試使用完畢
在lua環(huán)境中使用protobuf
https://blog.csdn.net/mergerly/article/details/16350871
最近在cocos2dx的項(xiàng)目中,需要在LUA腳本層使用protobuf協(xié)議。官方已經(jīng)推出了很多種語言的版本。但唯獨(dú)LUA版本不全。于是開始研究protobuf在LUA下的實(shí)現(xiàn),將完整的過程記錄了下來,希望對(duì)其它人能有所幫助。
1、下載protoc-gen-lua
可以通過HG從服務(wù)器(hg clone https://code.google.com/p/protoc-gen-lua/)上下載最新的版本。
簡單介紹一下里面的三個(gè)目錄:
example 存放的一個(gè)示例協(xié)議,
plugin 將.proto協(xié)議轉(zhuǎn)為LUA腳本需要的工具。要注意,這個(gè)工具是用PYTHON寫的,所以后面我們需要安裝PYTHON。
rotobuf這里存放了工程需要的文件。其中pb.c是C碼文件。主要是在工程中引用,也可以編譯成動(dòng)態(tài)文件(.so)供LUA調(diào)用。其它LUA文件則需要引入到LUA工程中。
2、安裝PYTHON27。推薦是這個(gè)版本。
3、下載protobuf然后編譯出protoc.exe。
可以用SVN從服務(wù)器上(http://protobuf.googlecode.com/svn/trunk)下載最新的protobuf。我使用的是protobuf-2.4.1。
進(jìn)入protobuf-2.4.1/vsprojects利用VS2010進(jìn)行編譯。生成的protoc.exe放到protobuf-2.4.1/src下。如果不放,后面無法安裝python版的protobuf。
4、編譯python版本的protobuf
在protobuf-2.4.1\python下運(yùn)行python setup.py build,然后再執(zhí)行python setup.py install。
注意:如果第3步的protoc.exe沒有放,會(huì)出現(xiàn)錯(cuò)誤找不到google\protobuf\compiler目錄。
5、制作轉(zhuǎn)換協(xié)議的批處理
在protoc-gen-lua/plugin目錄下編寫批處理:protoc-gen-lua.bat,就下面一行代碼。
///////////////////////////////////////////////////////////////////////////////////////
@python "%~dp0protoc-gen-lua"
///////////////////////////////////////////////////////////////////////////////////////
但要確保你的python命令能正常運(yùn)行。否則將python.exe所在的目錄加到環(huán)境變量path中。
接著拷貝一份protoc.exe到protoc-gen-lua目錄。第3步我們已經(jīng)編譯了出了protoc.exe。在協(xié)議轉(zhuǎn)換中,我們需要使用他。
在protoc-gen-lua目錄編寫批處理:buildproto.bat 來轉(zhuǎn)換協(xié)議。
- rem 切換到.proto協(xié)議所在的目錄
- cd ../luascript
- rem 將當(dāng)前文件夾中的所有協(xié)議文件轉(zhuǎn)換為lua文件
- for %%i in (*.proto) do (
- echo %%i
- "..\protobuf\protoc\protoc.exe" --plugin=protoc-gen-lua="..\protobuf\plugin\protoc-gen-lua.bat" --lua_out=. %%i
-
- )
- echo end
- pause
請(qǐng)正確指定protoc.exe和protoc-gen-lua.bat相對(duì)協(xié)議目錄的路徑。
6、轉(zhuǎn)換協(xié)議文件
protoc-gen-lua/example目錄中,有一個(gè)協(xié)議文件person.proto,可以拿他做一下試驗(yàn),會(huì)生成一個(gè)person_pb.lua
7、編譯pb.c文件
protoc-gen-lua/protobuf目錄中有一個(gè)pb.c文件。我們需要用他來協(xié)助lua完成protobuf的功能。
用vs2010新建一個(gè)控制臺(tái)程序。將pb.c加入到工程中。在windows平臺(tái)下,要對(duì)pb.c做如下修改。
1)將 #include <endian.h>修改為
#ifndef _WIN32
#include <endian.h>
#endif
避免在windows下缺失文件報(bào)錯(cuò).
2)調(diào)整struct_unpack函數(shù)前幾行為
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)在主函數(shù)前面申明pb.c的入口。
extern "C" { int luaopen_pb (lua_State *L);} // 注意防在命名空間外的全局聲明
編寫主函數(shù)如下:
- #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的接入。這個(gè)請(qǐng)自行編譯。
8、編寫main.lua。
也就是測(cè)試文件,可以參考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)
9、測(cè)試
編譯并運(yùn)行VS工程。運(yùn)行目錄應(yīng)該是LUA文件所在的目錄。運(yùn)行結(jié)果如下:

10、總結(jié)。
這里實(shí)現(xiàn)了,在C++中搭建lua的protobuf環(huán)境。但未實(shí)現(xiàn)純粹的Lua-protobuf環(huán)境。
如果需要在LUA中實(shí)現(xiàn)protobuf,那需要自己將pb.c編譯成dll。在linux下需要利用protoc-gen-lua/protobuf中的makefile將pb.c編譯成pb.so。
然后將pb.so或pb.dll導(dǎo)入到lua工程中。然后在main.lua中調(diào)用pb.c中的入口,代碼如下:
- local a = package.loadlib("pb.dll", "luaopen_pb");
- a()
理論上是這樣,我還沒有做詳細(xì)的測(cè)試。如果有進(jìn)展,再完善本貼。
轉(zhuǎn)自: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
然后進(jìn)入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.protogooglehttps://developers.google.com/protocol-buffers/docs/pythontutorial報(bào)錯(cuò)package directory 'google/protobuf/compiler' does not exist解決 https://groups.google.com/forum/?fromgroups=#!topic/protobuf/YeT5RW4qCxYpython ./setup.py buildsudo python ./setup.py install報(bào)錯(cuò) 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=438Log messageFix issue 438 : add missing 'enum_type_wrapper' to setup.py是安裝包的一個(gè)改進(jìn)文件,copy下來, 重新安裝根據(jù)安裝目錄下的demo 自己改寫了個(gè)簡單的, 覺得它那個(gè)還是麻煩write.pyimport testpb_pb4import sysp = 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 = 32p.str = "test"f = open(sys.argv[1], "wb")f.write(p.SerializeToString())f.close()print "write success"編譯指令 python write.py "test"read.py import sysimport testpb_pb2if 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.strprint "p.id=", p.id編譯指令 python read.py "test"
--------------------------------------------------------------------------------------------------------------------
LuaJIT下載:
http://luajit.org/download/LuaJIT-2.1.0-beta3.zip
.lib轉(zhuǎn)換為.a之后MinGW編譯引用(Windows平臺(tái))
http://www.shnenglu.com/kenkao/archive/2018/06/13/215724.html
protobuf_lua及pb.dll:(建議使用mingw編譯)
http://www.shnenglu.com/Files/kenkao/protobuf_lua.zip
openresty環(huán)境直接在nginx.conf中設(shè)置lua的腳本引用路徑及庫路徑:
lua_package_path 'lua/?.lua;pb/?.lua;';
lua_package_cpath '/usr/local/lib/lua/5.1/?.so;';
posted on 2018-06-06 16:57
思月行云 閱讀(7394)
評(píng)論(1) 編輯 收藏 引用 所屬分類:
Nginx\Openresty