使用c语言库asn1c对asn文件格式实现编解码

    针对asn文件编解码工作,asn1c这个开源工具对c/c++的支持非常好。可以很方便的安装和使用,目前这个工具是开源的,最新版本是0.9.28,项目地址:github.com/vlm/asn1c。官方文档地址:Open Source ASN.1 Compiler: asn1c 0.9.28。

    这个工具在linux上的安装很方便。

    这个工具还有一个很方便的地方在于,它可以直接将asn文件转化为c语言项目所需要的的头文件和源文件。

    下面通过一个简单的示例来演示如何通过asn1c这个工具来实现asn格式数据编解码。

     1、准备asn文件:

RectangleTest DEFINITIONS ::= BEGIN
Rectangle ::= SEQUENCE {
  height INTEGER,
  width INTEGER
}
END

      2、在该文件当前目录运行生成命令

asn1c -gen-PER *.asn

    运行该命令,会在本目录下生成很多头文件和源代码文件。其中包含一个拥有main主函数的测试代码,一般我们不使用这个源代码来运行示例,自己编写一个。

使用c语言库asn1c对asn文件格式实现编解码_第1张图片

     3、自己编写一个main.c代码如下:

#include 
#include 
#include "Rectangle.h"
static int write_out(const void *buffer,size_t size,void *key)
{
  FILE *out_fp = key;
  return (fwrite(buffer,1,size,out_fp)==size)?0:-1;
}
int main()
{
  Rectangle_t *rect;
  asn_enc_rval_t ec;
  rect = calloc(1,sizeof(Rectangle_t));
  //init rect
  rect->width = 23;
  rect->height = 42;
  const char* filename = "Test";
  FILE *fp = fopen(filename,"wb");
  ec = uper_encode(&asn_DEF_Rectangle,rect,write_out,fp);
  if(ec.encoded==-1){
    printf("encode error.\n");
  }else{
    printf("encode ok,result in %s.\n",filename);
  }
  return 0;
}

    这段代码很简单,主要定义了一个写入函数,作为uper_encode的回调函数,在这个函数里面,将编码后的结果写入文件,这个文件在本示例里面用Test命名。

     4、 编译,运行,如果不出错,那么就是编码成功。这里稍微提一下,编译命令:

gcc -o main -I. *.c

    这里的-I.参数指的是,包含本目录。 

     5、这个结果还不好验证。但是我们可以通过一个asn在线编译器进行验证。 在这个页面,有三个视图,在最左边的视图,我们手动输入我们上面的asn文件内容:

使用c语言库asn1c对asn文件格式实现编解码_第2张图片

 

    在第二个部分,我们通过json格式把代码中的参数设置进去。

使用c语言库asn1c对asn文件格式实现编解码_第3张图片

    点击第二个试图中的Encode,如果没有报错,那么页面最右侧的第三个控制台输出试图里面就会显示编码结果,各个类型的都会列出来,这里我们关注这个示例中的uper类型,结果是012a0117。

使用c语言库asn1c对asn文件格式实现编解码_第4张图片 

    这个是通过三方网站来验证我们的编码结果。

    接着我们把linux上的编码结果文件Test下载到windows上,使用notepad++打开,通过hex插件,可以查看16进制表示,结果与上面的编码是一致的:

使用c语言库asn1c对asn文件格式实现编解码_第5张图片 

    至此,我们通过一个简单的示例,实现了asn编码。编码类型采用的是uper,因为这个在实际中使用的很广泛。

    6、接着改动main.c文件,实现解码功能,大致意思是读取Test文件,然后通过asn1c提供的解码方法uper_decode()解码。代码如下:

#include 
#include 
#include "Rectangle.h"
int main()
{
  Rectangle_t *rect;
  asn_dec_rval_t dc;
  char buf[20];
  rect = calloc(1,sizeof(Rectangle_t));
  const char* filename = "Test";
  FILE *fp = fopen(filename,"r");
  size_t size;
  size = fread(buf,1,sizeof buf,fp);
  asn_codec_ctx_t *opt_codec_ctx = 0;
  dc = uper_decode(opt_codec_ctx,&asn_DEF_Rectangle,(void **)&rect,buf,size,0,0);
  if(dc.code==-1){
    printf("decode error.\n");
  }else{
    printf("decode ok,rect's width=%d,height=%d.\n",rect->width,rect->height);
  }
  return 0;
}

     7、编译,运行代码,打印截图如下:

使用c语言库asn1c对asn文件格式实现编解码_第6张图片

    解码成功。 

你可能感兴趣的:(c++,asn1c,uper,asn,c/c++,encode/decode)