处理外来二进制数据的约定



我是一名C程序员,几周前开始学习Ada。我一直对Ada如何处理外来二进制数据感到困惑,比如在解码存储在串行输入缓冲区中的通信数据包时。

在C中,我会定义一个打包结构来反映数据包的布局,然后将指针到缓冲区转换为指针到结构,以访问通信数据中的各个元素。在Ada中进行这种解码的典型方法是什么?

我尝试用以下在Ada中复制C的相同方法

-- Fundamental types for fields in the packet
type Station_Addr_Type is mod 2**8;
type Func_Code_Type is (FUNC1, FUNC2);
for Func_Code_Type use
(
FUNC1 => 1,
FUNC2 => 2
);
type Packet is
record
Station_Addr : Station_Addr_Type;
Func_Code : Func_Code_Type;
end record;

-- attempts to reflect packet binary layout
for Packet use
record at mod 1;
Station_Addr at 0 range 0 .. 7;
Func_Code at 1 range 0 .. 7;
end record;

然后,我为接受外来二进制数据(可能来自不同架构(的通信接收缓冲区定义了阵列:

type Communication_Data is mod 2**8;
for Communication_Data'Size use 8;
type Communication_Buffer is array (Natural range <>) of Communication_Data;
Buffer : Communication_Buffer (0 .. 20);

然后解码这种通信的程序

procedure Decode_Packet (Packet_Provided : in Packet);
-- non-working sample
declare
begin
-- Attempts to sanity-check packet by object casting
Decode_Packet (Packet (Buffer));
---------------^----
Error: invalid conversion, not compatible with type "Communication_Buffer"
exception
when others => 
raise Decode_Failure;
end;

但是,编译器禁止这种带有错误的强制转换,如图所示。谢谢你读到这里。我的问题是,

关于解码外来二进制数据的正确方式;在球场";,或者有更好的方法吗?

  1. 如果您确定数据对齐正确,您可以将数据包对象映射到Communication_data分配的空间:
Buffer : Communication_Buffer (0 .. 20);
Pkg    : Packet;
pragma Import (Ada, Pkg);
for Pkg'Address use Buffer (0)'Address;

与方面语法相同:

Buffer : Communication_Buffer (0 .. 20);
Pkg    : Packet
with Import, Address => Buffer (0)'Address;
  1. 另一种方法是使用Ada.Unchecked_Conversion,但您应该确保Buffer和Packet具有相同的大小:
subtype Packet_Buffer is Communication_Buffer (1 .. 2);
function To_Packet is new Ada.Unchecked_Conversion
(Packet_Buffer, Packet);
Pkg : Packet := To_Packet (Buffer (0 .. 1));

PS。如果您想要独立于endianness的代码,您可能还需要Scalar_Storage_Order(GNAT实现定义(方面。

PS。我还建议看一下";"安全通信";安全软件手册的第章。

最新更新