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

Convention for handling foreign binary data

我是一名 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. 如果您确定数据正确对齐,则可以将 Packet 对象映射到由 Communication_Data:
  2. 分配的 space
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。如果你想要一个字节顺序无关的代码,你可能还需要一个 Scalar_Storage_Order(GNAT 实现定义)方面。

PS。我还建议您查看 Safe and Secure Software 小册子的“安全通信”一章。