处理外部二进制数据的约定
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;
但是,编译器禁止这样的转换,并出现如图所示的错误。感谢您阅读到这里。我的问题是,
关于解码外国二进制数据的正确方法,我是否“在球场上”,或者有更好的方法吗?
- 如果您确定数据正确对齐,则可以将 Packet 对象映射到由 Communication_Data:
分配的 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;
- 另一种方法是使用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 小册子的“安全通信”一章。
我是一名 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;
但是,编译器禁止这样的转换,并出现如图所示的错误。感谢您阅读到这里。我的问题是,
关于解码外国二进制数据的正确方法,我是否“在球场上”,或者有更好的方法吗?
- 如果您确定数据正确对齐,则可以将 Packet 对象映射到由 Communication_Data: 分配的 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;
- 另一种方法是使用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 小册子的“安全通信”一章。