返回一个胖/粗指针作为out参数

时间:2013-03-18 12:03:29

标签: ada

我在创建粗指针时遇到问题。我目前的一组声明如下:

type Index_Typ is mod 20; -- will be larger in real life
type Data_Buffer_Typ is array (Index_Typ range <>) of Integer; --unconstrained array type
type Data_Buffer_Ptr is access all Data_Buffer_Typ; -- a thick pointer, contains the bounds of array subtype pointed to and address..

Data_Buffer : aliased Data_Buffer_Typ (Index_Typ) := (others => 0); -- this is private
type Result_Typ is (Ok, Overflow, Null_Pointer);

   procedure Retrieve (Index    : in     Index_Typ;
                       Len      : in     Index_Typ;
                       Data_Ptr :    out Data_Buffer_Ptr;
                       Result   :    out Result_Typ) is
   begin
     -- assuming range checks are ok, what goes here ?
   end Retrieve;

所以,如果我宣布:

Ptr : Data_Buffer_Ptr := null;

并且给出了Retreive (2,3, Ptr,Result);的调用,我如何得到一个指向元素2,3&amp;的指针。 4 Data_Buffer

注意:

  • 是的,我知道传出一个数组切片可能会作为一个 无论如何指针,但我们想明确使用指针,而不是 隐含地(而不是我的选择!)。
  • 是的,我已经尝试过,我通常得到:(object subtype must statically match designated subtype)错误消息..
  • 尽可能使用new

1 个答案:

答案 0 :(得分:1)

这对我有用,虽然我不得不说这是令人厌恶的!请注意Fat_Pointer中组件的顺序,这与我开始的相反,以及此64位计算机上的记录大小(我将rep子句放入以使命令显式,它工作正常没有)。另外,我认为你坚持使用new

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Conversion;
with System;
procedure Fat is
   type Index_Typ is mod 20;
   type Data_Buffer_Typ is array (Index_Typ range <>) of Integer;
   type Data_Buffer_Ptr is access all Data_Buffer_Typ;
   Data_Buffer : aliased Data_Buffer_Typ (Index_Typ) := (others => 0);
   type Result_Typ is (Ok, Overflow, Null_Pointer);

   procedure Retrieve (Index    : in     Index_Typ;
                       Len      : in     Index_Typ;
                       Data_Ptr :    out Data_Buffer_Ptr;
                       Result   :    out Result_Typ)
   is
      type Bound is (Lower, Upper);
      type Bounds is array (Bound) of Index_Typ;
      type Bounds_P is access Bounds;
      type Fat_Pointer is record
         The_Data : System.Address;
         The_Bounds : Bounds_P;
      end record;
      for Fat_Pointer use record
         The_Data at 0 range 0 .. 63;
         The_Bounds at 8 range 0 .. 63;
      end record;
      function To_Data_Buffer_Ptr
      is new Ada.Unchecked_Conversion (Fat_Pointer, Data_Buffer_Ptr);
      Answer : constant Fat_Pointer
        := (The_Bounds => new Bounds'(Lower => Index,
                                      Upper => Index + Len - 1),
            The_Data => Data_Buffer (Index)'Address);
   begin
      Result := Ok;
      Data_Ptr := To_Data_Buffer_Ptr (Answer);
   end Retrieve;

   Ptr : Data_Buffer_Ptr := null;
   Result : Result_Typ;

begin
   for J in Data_Buffer'Range loop
      Data_Buffer (J) := Integer (J);
   end loop;

   Retrieve (2, 3, Ptr, Result);

   for J in Ptr'Range loop
      Put_Line (J'Img & " => " & Ptr (J)'Img);
   end loop;
end Fat;