Wrapping an imported C pointer in an Ada tagged type of the same size

I'd like to replicate a C struct memory layout into an Ada type, and at the same time wrap the C fields (which are pointers) into tagged types that are at the same memory locations as the pointers to avoid extra memory use, while using dot notation on the pointee information in a confortable Ada way. This requires that the tagged Ada fields have the same size as the C pointers.

An example that works without tagged types is as follows:

with Ada.Text_IO; use Ada.Text_IO;

procedure Tag is

   package P is 

      type Int_Ptr is access all Integer with Convention => C;

      --  This would be in reality a C record
      type Rec is record
         I : Int_Ptr := new Integer'(42);
      end record
        with Convention => C;

      --  This is the field wrapper that would be tagged
      type Wrap_I is record -- Making this tagged breaks it
         I : Int_Ptr;
      end record
        with Convention => C;

      function Image (WI : Wrap_I) return String is

      --  This is the Ada type corresponding to C Rec
      type Wrap_Rec is record
         I : Wrap_I;
      end record
        with Convention => C;

   end P;

   R : P.Rec;
   W : P.Wrap_Rec with Address => R'Address, Import;

   Put_Line (P.Image (W.I));  -- Should be 42 if properly overlaid

   --  This is the objective: to use dot notation on C pointed data:
   -- Put_Line (W.I.Image);
end Tag;

Now, the objective is to make Wrap_I tagged. Once I mark it as such, GNAT warns that R and W sizes differ (and it raises a tag check failed at runtime, obviously). I do not need dispatching or anything but static calls, so in essence I wonder if there is a way of having a tagged type without storing its tag in memory (to be used statically only).

I have a much more traditional plan B so no need to suggest alternatives if this is not doable.



  • You can't have tagged types without tags, so it isn't doable.