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
=============================================================