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

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

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

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

刪除后如下圖

項目一個一個編譯,不要一起編譯。
首先來編譯 libprotobuf 項目,肯定會出錯。提示如下錯誤

原因是Protobuf 中沒有添加對應的頭文件,在項目中 搜索打開 common.h ,添加對應頭文件,如下圖:

再次編譯,就可以編譯成功。
然后編譯 第二個項目 libprotobuf-lite 。不會出錯。
然后再編譯 第三個項目 libprotoc 。肯定會出錯,如下圖

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

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

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

在 plugin 目錄 創建 批處理文件 protoc-gen-lua.bat , 內容如下
- @python "%~dp0protoc-gen-lua"
然后將 上一步 編譯 protobuf-2.4.1 中生成的 protoc.exe 拷貝到 protoc-gen-lua-master 目錄,如下圖
然后在 protoc-gen-lua-master 目錄下創建批處理文件 buildproto.bat ,內容如下
- rem 切換到.proto協議所在的目錄
- cd protobuf\luascript
- rem 將當前文件夾中的所有協議文件轉換為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
這個批處理的作用是:先進入到一個文件夾,然后將該文件夾中的 proto 文件 生成 lua 文件。 我這里是進入到 protoc-gen-lua-master\protobuf\luascript 。所以我在 protobuf 目錄下新建 目錄 luascript ,在該目錄進行 proto 轉換 lua 。如果需要在其它目錄進行,要把上面批處理的內容修改目錄為自己想要的。
好,下面來測試一下。
在 protoc-gen-lua-master\example 目錄下有一個測試的 proto 文件 person.proto ,把它拷貝到 luascript 文件夾。

然后 返回執行上面創建的批處理文件 buildproto.bat 。 本文轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

生成成功,到 luascript 中查看,看到生成了對應的 lua 文件 person_pb.lua 。

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

在 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;
- }
設置 頭文件引用路徑為 LuaJIT-2.0.4\src 目錄
設置鏈接器附加庫目錄為 LuaJIT-2.0.4\src 目錄
設置鏈接器附加依賴項為 lua5.1.4.lib
然后編譯,肯定會報錯。。如下圖

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

就是用 宏定義 來判斷,在Windows 系統下不引用 endian.h 這個文件。
再次編譯,肯定成功。
在上面的代碼中,我們加載了一個 lua 腳本文件 main.lua 。
我們在項目目錄中新建 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 代碼里面,我們 測試了 對 person 的序列化 和 反序列化 。
還記得之前生成的 person_pb.lua 文件嗎?在 protoc-gen-lua-master\protobuf\luascript 目錄里。
我們把整個 protoc-gen-lua-master\protobuf 目錄拷貝到測試項目 目錄 里來。因為 main.lua 中要引用這些 lua 文件。

然后運行測試項目

序列化 和 反序列化 測試成功
測試工程下載
- http://pan.baidu.com/s/1ntvlBp3
至此, protoc-gen-lua 編譯 測試使用完畢
在lua環境中使用protobuf
https://blog.csdn.net/mergerly/article/details/16350871
最近在cocos2dx的項目中,需要在LUA腳本層使用protobuf協議。官方已經推出了很多種語言的版本。但唯獨LUA版本不全。于是開始研究protobuf在LUA下的實現,將完整的過程記錄了下來,希望對其它人能有所幫助。
1、下載protoc-gen-lua
可以通過HG從服務器(hg clone https://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.1\python下運行python setup.py build,然后再執行python setup.py install。
注意:如果第3步的protoc.exe沒有放,會出現錯誤找不到google\protobuf\compiler目錄。
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
- "..\protobuf\protoc\protoc.exe" --plugin=protoc-gen-lua="..\protobuf\plugin\protoc-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)
9、測試
編譯并運行VS工程。運行目錄應該是LUA文件所在的目錄。運行結果如下:

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.protogooglehttps://developers.google.com/protocol-buffers/docs/pythontutorial報錯package directory 'google/protobuf/compiler' does not exist解決 https://groups.google.com/forum/?fromgroups=#!topic/protobuf/YeT5RW4qCxYpython ./setup.py buildsudo 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=438Log messageFix issue 438 : add missing 'enum_type_wrapper' to setup.py是安裝包的一個改進文件,copy下來, 重新安裝根據安裝目錄下的demo 自己改寫了個簡單的, 覺得它那個還是麻煩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轉換為.a之后MinGW編譯引用(Windows平臺)
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環境直接在nginx.conf中設置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
思月行云 閱讀(7395)
評論(1) 編輯 收藏 引用 所屬分類:
Nginx\Openresty