You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用asn1c编译器处理ASN.1矩形/圆形结构的动态解码问题

解决ASN.1动态识别结构类型的解码问题

方案一:自定义标识头实现(符合你的初始思路)

编码步骤

  • 定义1字节类型标识:比如0x01代表矩形(Rectangle),0x02代表圆形(Circle)
  • 调用uper_encode()对目标结构编码,得到二进制数据
  • 将标识字节与编码后的数据拼接成完整发送缓冲区

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Mystructs.h" // asn1c生成的头文件

// 编码并添加标识头
int encode_with_header(void *struct_ptr, asn_TYPE_descriptor_t *td, uint8_t type_id, uint8_t **out_buf, size_t *out_len) {
    uint8_t *encoded_data = NULL;
    size_t encoded_len = 0;

    // 执行UPER编码
    asn_enc_rval_t er = uper_encode(td, struct_ptr, NULL,
        (asn_app_consume_bytes_f)asn_write_out, &encoded_data);
    if (er.encoded == -1) {
        fprintf(stderr, "编码失败\n");
        return -1;
    }
    encoded_len = er.encoded;

    // 分配缓冲区:1字节标识 + 编码数据
    *out_buf = malloc(1 + encoded_len);
    if (!*out_buf) {
        free(encoded_data);
        return -1;
    }
    (*out_buf)[0] = type_id;
    memcpy(*out_buf + 1, encoded_data, encoded_len);
    *out_len = 1 + encoded_len;

    free(encoded_data);
    return 0;
}

// 使用示例:编码矩形
int main() {
    Rectangle_t rect = {.height = 100, .width = 200};
    uint8_t *send_buf = NULL;
    size_t send_len = 0;
    
    if (encode_with_header(&rect, &asn_DEF_Rectangle, 0x01, &send_buf, &send_len) == 0) {
        // 此处添加发送逻辑
        free(send_buf);
    }
    return 0;
}

解码步骤

  • 先读取第一个字节的标识值
  • 根据标识选择对应的ASN.1类型描述符
  • 调用uper_decode()解码剩余的二进制数据

示例代码:

// 解码带标识头的数据
void decode_with_header(uint8_t *in_buf, size_t in_len) {
    if (in_len < 1) {
        fprintf(stderr, "数据长度不足\n");
        return;
    }

    uint8_t type_id = in_buf[0];
    uint8_t *encoded_data = in_buf + 1;
    size_t encoded_len = in_len - 1;

    asn_TYPE_descriptor_t *td = NULL;
    void *struct_ptr = NULL;

    // 根据标识匹配对应类型
    switch (type_id) {
        case 0x01:
            td = &asn_DEF_Rectangle;
            struct_ptr = calloc(1, sizeof(Rectangle_t));
            break;
        case 0x02:
            td = &asn_DEF_Circle;
            struct_ptr = calloc(1, sizeof(Circle_t));
            break;
        default:
            fprintf(stderr, "未知类型标识\n");
            return;
    }

    if (!struct_ptr) {
        fprintf(stderr, "内存分配失败\n");
        return;
    }

    // 执行UPER解码
    asn_dec_rval_t dr = uper_decode(NULL, td, &struct_ptr, encoded_data, encoded_len, 0, 0);
    if (dr.code != RC_OK) {
        fprintf(stderr, "解码失败\n");
        td->free_struct(td, struct_ptr, 0);
        return;
    }

    // 处理解码结果
    if (type_id == 0x01) {
        Rectangle_t *r = (Rectangle_t *)struct_ptr;
        printf("解码矩形:height=%d, width=%d\n", r->height, r->width);
    } else if (type_id == 0x02) {
        Circle_t *c = (Circle_t *)struct_ptr;
        printf("解码圆形:radius=%d\n", c->radius);
    }

    // 释放资源
    td->free_struct(td, struct_ptr, 0);
}

方案二:用ASN.1 CHOICE类型原生支持(更规范)

直接修改ASN.1定义,用CHOICE类型包装Rectangle和Circle,UPER编码会自动包含类型标识,无需手动处理头信息。

修改后的ASN.1代码:

Mystructs DEFINITIONS ::= BEGIN

Rectangle ::= SEQUENCE {
    height INTEGER (0..255),
    width INTEGER (0..255)
}  

Circle ::= SEQUENCE {
    radius INTEGER (0..255)
}

Shape ::= CHOICE {
    rectangle Rectangle,
    circle Circle
}

END

编码和解码示例

用asn1c重新编译后,直接使用Shape_t结构体:

#include <stdio.h>
#include "Mystructs.h"

// 编码示例
void encode_shape() {
    Shape_t shape = {.present = Shape_PR_rectangle};
    shape.choice.rectangle.height = 100;
    shape.choice.rectangle.width = 200;

    uint8_t *encoded_data = NULL;
    asn_enc_rval_t er = uper_encode(&asn_DEF_Shape, &shape, NULL,
        (asn_app_consume_bytes_f)asn_write_out, &encoded_data);
    
    if (er.encoded != -1) {
        // 发送encoded_data
        free(encoded_data);
    }
}

// 解码示例
void decode_shape(uint8_t *recv_buf, size_t recv_len) {
    Shape_t *decoded_shape = NULL;
    asn_dec_rval_t dr = uper_decode(NULL, &asn_DEF_Shape, (void **)&decoded_shape,
        recv_buf, recv_len, 0, 0);
    
    if (dr.code == RC_OK) {
        switch (decoded_shape->present) {
            case Shape_PR_rectangle:
                printf("矩形:height=%d, width=%d\n", decoded_shape->choice.rectangle.height, decoded_shape->choice.rectangle.width);
                break;
            case Shape_PR_circle:
                printf("圆形:radius=%d\n", decoded_shape->choice.circle.radius);
                break;
            default:
                break;
        }
        ASN_STRUCT_FREE(asn_DEF_Shape, decoded_shape);
    }
}

内容的提问来源于stack exchange,提问作者José

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:25:37