1 使用asn1c實現編碼
參考網址:http://lengxuezhixuan.blog.chinaunix.net/uid-28765492-id-3765759.html
PS:這個網址就是根據下載的asn1c中的英文指導文檔做的。
* 遇到的問題:
(1)頭文件的引用:頭文件放在了vc/include下,對.h文件可以使用include<>。對於本工程下的.h文件使用include""
(2)如果cpp與c文件共存,會有預編譯頭不兼容的問題,可以設置所有源文件的屬性去掉預編譯頭,或者將所有代碼調整成cpp或c
****************************************************************************************************
本人所做的實驗是用c編碼、用java解碼:將編碼結果直接用%s輸出到txt文件,之後用java解碼就實現了不同語言間序列化數據的使用(其實都用不到asn文件,用c編碼時只是需要利用asn文件生成那一系列c文件;解碼就更不需要asn了)
PS:之後編了一個複雜的,各種報錯類型找不到,浪費了一個小時才發現asn-0.9.21的類型定義名稱和網上的不一樣(要去sketon裏面找),好坑。編碼時自己設計的結構名name會被typedef成name_t!
=============================================================
2 使用javaAsn1Comilper解碼(參考javaAsn1Comilper指導文檔的示例)
(1)TestUtil是一個示例,可以不要(裏面有結構化輸出,可以直接copy一下);TestParser也可以不要,需要同時刪掉另外一個繼承了它的類
(2)爲自己設計的結構裏的元素分別創建類,並分別繼承相應的類型:爲rectangle的內容創建一個類width(繼承ASN1Integer)
package com.chaosinmotion.asn1;
public class width extends ASN1Integer {
public width(){//默認是5
super(5);
}
public width(long value){//設置大小
super(value);
}
}
(3)創建自己設計的那個結構的類:創建類Rectangle。必須用super.addElement爲結構添加元素,否則該結構裏啥也沒有
package com.chaosinmotion.asn1;
public class BerRectangle extends Sequence {
public ASN1Integer length=new width();
public ASN1Integer width=new width();
public BerRectangle() {
super();
setUp();//必須使用addElement爲sequence添加內容,否則成爲未初始化
}
protected void setUp(){
super.addElement(length);
super.addElement(width);
}
}
(4)實現應用:就按文檔給的來!
public static void main(String[] args){
BerRectangle test=new BerRectangle();//創建對象
test.width.setValue(23);//初始化對象
test.length.setValue(42);
//將對象編碼
ByteArrayOutputStream stream=new ByteArrayOutputStream();//必有
BerOutputStream out=new BerOutputStream(stream);//必有
try {
test.encode(out);//必有
printData(stream.toByteArray());//copy的TestUtil的結構化輸出方法
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("error");
e.printStackTrace();
}
//解碼
ByteArrayInputStream destream=new ByteArrayInputStream(stream.toByteArray());
BerInputStream in=new BerInputStream(destream);
BerRectangle test2=new BerRectangle();//必有,創建一個實體
try {
test2.decode(in);//必有,in其實就是編碼好的那串二進制,所以也可以是從文件讀來;將in解碼並放到test2中
System.out.println(test2);//直接輸出就可以
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("over");
}
=============================================================
3 protobuf實現asn1
首先,protobuf安裝(系統環境:windows)
(參考protobuf源碼的README.md,無調整)
1 安裝cmake
網址:https://cmake.org/download/
本人直接下載的installer :)
2 安裝git
網址:https://git-scm.com/download/win
同樣,直接下載的二進制版本的,點擊&finish :)
3 安裝protobuf
3.1按照readme的指示
3.1.1 設置cmake和git的使用路徑
本人要將protobuf安裝在"f:\新建文件夾"裏,set PATH是設置臨時環境變量
f:
cd 新建文件夾
set PATH=%PATH%;"c:\Program Files (x86)\Cmake\bin"
set PATH=%PATH%;"c:\Program Files\Git\cmd"
3.1.2 獲得protobuf源碼:本人下載的master版的
git clone -b master https://github.com/google/protobuf.git
3.1.3 獲得gmock(反正protobuf readme這麼說的)
cd protobuf
git clone -b release-1.7.0 https://github.com/google/googlemock.git gmock
cd gmock
git clone -b release-1.7.0 https://github.com/google/googletest.git gtest
3.1.4 使用cmake製作sln(可以用圖形化的,也可以用命令行——本人的編譯器是vs2010)
(1)本人用的圖形化版的cmake來生成IDE使用的sln
source是protobuf/cmake;dst是protobuf/cmake/build/Debug(build/Debug是自己設的路徑,爲了做錯時好刪).
generate前先點擊file的delete cache;然後configue,然後generate。
完成後就可以在Debug裏找到protobuf.sln
(2) 命令行生成sln:
語句如下:
cmake -G "Visual Studio 10 2010 Win64" ^
-DCMAKE_BUILD_TYPE=Debug ^
-DCMAKE_INSTALL_PREFIX=../../../../install ^
../.. ^
-DCMAKE_CXX_COMPILER="F:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin/cl.exe" ^
-DCMAKE_C_COMPILER="F:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin/cl.exe"
本人的IDE是vs2010 win64的(可以用cmake --help查看cmake支持的IDE種類);生成類型是Debug(與文件名無關);
最後兩行是設置c和cxx編譯器地址,即IDE文件夾中的cl.exe的絕對路徑;
(如果提示mspdb100.dll找不到,需要path=%path%;F:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE)
注意:輸入路徑時注意一定用/(cmake語法)和""(因爲用空格斷句,所以路徑裏有空格要用""包起來)。
3.1.5 編譯,可以使用IDE打開protobuf.sln直接build solution(因爲命令行不好做,所以本菜鳥就用了IDE)
3.1.6 安裝,打開protobuf.sln
(1)首先build 整個solution
(2)build 三個:libprotobuf,libprotoc,libprotobuf-lite,protoc;結果會在工程目錄下的Debug中(protoc.exe libprotobuf-lite.lib libprotobufd.lib libprotocd.lib)
PS:readme中讓build install,但我只在使用master版是成功過一次,之後一直失敗,不知道怎麼辦,但是不影響應用也就沒管(懶)
3.2 按照網上的教程也是一樣的,只是不用git,直接手動去網站下載;網址:https://developers.google.com/protocol-buffers/docs/downloads。
網上使用的版本中都有vsproject目錄,所以可以直接進行3.1.5;但我下載的版本里面都沒有現成的vsproject,需要自己生成,所以cmake、gmock還是要裝的,只是省掉了2和3.1.2
=============================================================
protobuf的應用(win&&c++)
1 編寫proto文件
本人編了一個最簡單的例子,具體語法什麼的可以去網上找。
message rectangle{
required int32 height = 1;
required int32 width = 2;
}
2 生成.cc和.h文件
cmd命令:protoc -I=C:\Users\chris\Desktop\ --cpp_out=C:\1 C:\Users\chris\Desktop\rectangle.proto
說明:
C:\Users\chris\Desktop\ 是我的proto文件所在目錄
C:\1 是目標目錄
C:\Users\chris\Desktop\rectangle.proto 是proto文件的絕對路徑
3 創建一個工程
3.1 添加protobuf的支持文件
protobuf/src/google和編譯源碼時生成的libprotobuf-lite.lib libprotobufd.lib libprotocd.lib
頭文件使用<>,因此需要將google添加到編譯器的vc/include目錄下(本人初始不知道<>是這個意思,嘗試將<>改爲"",但總是失敗,最後放棄)
將libprotobuf-lite.lib libprotobufd.lib libprotocd.lib添加到工程目錄下,使用絕對路徑加載(當然也有別的辦法,本人。。懶)
3.2 將之前生成的.cc和.h放進來
3.3 編寫main函數對rectangle進行應用
#include "rectangle.pb.h"
#include <iostream>
#include <string>
using namespace std;
#pragma comment(lib,"C:\\Users\\chris\\Desktop\\protodemo\\protodemo\\libprotocd.lib")
#pragma comment(lib,"C:\\Users\\chris\\Desktop\\protodemo\\protodemo\\libprotobufd.lib")
//#pragma comment(lib,"C:\\Users\\chris\\Desktop\\protodemo\\protodemo\\libprotobufd-lite.lib")
int main(int,char**){
rectangle test1,test2;
string data;
//初始化test1
test1.set_height(42);
test1.set_width(23);
test1.SerializeToString(&data);//對test1進行編碼,結果放在data中
test2.ParseFromString(data);//將序列data解碼,結果賦給test2
cout<<data<<"\n"<<"test2\n hieght:"<<test2.height()<<"\n width:"<<test2.width()<<"\n";
return 0;
}
PS:使用的頭文件、lib、用於生成.cc和.h的protoc的版本要一致;創建的工程的propertis->c/c++->code generation的runtime改爲MTD
=============================================================