python調用動態鏈接庫傳送protobuf數據

原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://padden.blog.51cto.com/2514314/441612


什麼是protobuf

   protobuf是Google提供的一個開源序列化框架,類似於XML,JSON這樣的數據表示語言,其最大的特點是基於二進制,因此比傳統的XML表示高效短小得多。開發者定義類似於結構體的message,通過protobuf的工具將定義好的格式傳送給protobuf的接收工具,接收工具會自動產生類,需要傳輸的時候直接導入這個類,將關鍵字段填充,通過序列化函數,將其序列化,接收端將其反序列化,實現數據傳輸。protobuf支持c++,java,python。詳細信息見參考文檔

  protobuf的格式定義,可以看文檔,這裏舉兩個簡單實用的例子:

 

  1. message User {  
  2.   required string username = 1;
  3. required string password = 2  
  4.   required int32 age = 3;  
  5.   optional string email = 4;  
  6.   }  
  7.  

 protobuf作爲一種數據表示語言,有自己的類型,如代碼中寫的string,int32,等等,required,optional代表這個字段是否是必填,必填寫required,不必填充寫optional。後面的1,2,3是序號,不是這個字段的值,必填字段是要在程序中進行填充,或者設置默認值。關於protobuf的類型和格式可以看Google Language Guide,如果想定義一個User數組進行傳輸,可以這樣定義(注意關鍵字repreated):

  1. message User {  
  2.   required string username = 1;  
  3.   required string password = 2;  
  4.   required int32 age = 3;  
  5.   optional string email = 4;  
  6.   }  
  7.  
  8. message Users {  
  9.   repeated User user = 1;  
  10.   }  
  11.  

  在定義好格式之後(message文件以.proto結尾),我們可以安裝protobuf的linux下的message生成工具,具體可以去Google官方下載,這是個開源項目,安裝的時候還是那幾步,./configure,make,make install,很簡單,前提需要gcc編譯器。然後安裝一個protobuf的類庫,這裏我以python2.5爲例,需要安裝類庫,protobuf-2.3.0-py2.5.egg,egg文件類似於c++中的.so或者是java中的jar文件,是一個庫文件,提供調用,安裝egg文件最簡單的方法是安裝easy_install,如果你不想安也可以,指定egg文件的路徑,但是這樣做會有些風險,因爲加載egg文件還需要一個python的庫setuptools-0.6c9-py2.5.egg,你可以這麼幹:

export PYTHONPATH=$SRC_DIR/protobuf-2.3.0-py2.5.egg:$SRC_DIR/setuptools-0.6c9-py2.5.egg

  這麼幹的目的是把這些庫文件導入python的sys.path路徑中,加載的時候也能加載到,這樣你在程序裏直接import google.protobuf,或者導入其他protobuf的庫 肯定不會報錯,c++和java就不細說了,大同小異。 

  安裝完成後,執行 protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/User.proto 如果,沒提示錯誤的話會在輸出目錄下生成 XXX_pb2.py文件(我上面定義的會生成User_pb2.py),這個就是生成的類,用的時候直接引入就可以(放在一個目錄下,或者導入sys.path)。

  關於python調用動態鏈接庫,python提供了一個庫,ctypes,這個庫2.4以及2.4之前都沒有,用的時候注意版本,調用如下:

  1. from ctypes import *  
  2. import User_pb2
  3.  
  4.  
  5. libs = CDLL("./libs.so")  
  6. libs.Init()  
  7. user = User_pb2.User() #類似於構造方法  
  8. user.username = 'zhangpeng' 
  9. user.password = 'xxxxxxxxx' 
  10. user.age = 23 
  11. sContent = user.SerializeToString() #序列化方法  
  12. libs.Send(c_char_p(sContent), c_uint(len(sContent)))  
  13. libs.IPCExit() 
  我只是粗略的寫一下,大家肯定一看就明白。如果傳送protobuf數組,就可以這樣寫:   
  1. from ctypes import *    
  2. import Users_pb2   
  3.  
  4.  
  5. libs = CDLL("./libs.so")    
  6. libs.Init()    
  7. users = User_pb2.Users() #類似於構造方法  
  8. user = users.add()    
  9. user.username = 'zhangpeng'   
  10. user.password = 'xxxxxxxxx'   
  11. user.age = 23   
  12. sContent = users.SerializeToString() #序列化方法    
  13. libs.Send(c_char_(sContent), c_uint(len(sContent)))    
  14. libs.IPCExit()  

  就這麼簡單,加一個add方法,注意User 和Users的區別,

  結束語:這個東西本來是要在c++中實現的,但是涉及的東西很多,改起來相對較麻煩,而且有風險,改成用py實現了,但是c肯定要比python的序列化效率高,個人認爲python更像一支粘合劑,很好用。有什麼問題直接指出,望賜教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章