From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 2002:aed:212b:: with SMTP id 40mr3555847qtc.206.1576082588623; Wed, 11 Dec 2019 08:43:08 -0800 (PST) X-Received: by 2002:a9d:4789:: with SMTP id b9mr3085806otf.110.1576082588303; Wed, 11 Dec 2019 08:43:08 -0800 (PST) Path: eternal-september.org!reader01.eternal-september.org!feeder.eternal-september.org!news.gegeweb.eu!gegeweb.org!usenet-fr.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!g89no4441300qtd.0!news-out.google.com!w29ni1010qtc.0!nntp.google.com!g89no4441298qtd.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Wed, 11 Dec 2019 08:43:08 -0800 (PST) Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=2a02:c7d:3c35:b000:325a:3aff:fe0f:37a5; posting-account=L2-UcQkAAAAfd_BqbeNHs3XeM0jTXloS NNTP-Posting-Host: 2a02:c7d:3c35:b000:325a:3aff:fe0f:37a5 User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <36d45c82-2a6b-4c60-baeb-1a4aef5189c7@googlegroups.com> Subject: Is this actually possible? From: Lucretia Injection-Date: Wed, 11 Dec 2019 16:43:08 +0000 Content-Type: text/plain; charset="UTF-8" Xref: reader01.eternal-september.org comp.lang.ada:57705 Date: 2019-12-11T08:43:08-08:00 List-Id: Hi, I was thinking about extensible records recently (not tagged types), and thought to try to export a tagged type to C, not C++. It compiles, but the results aren't quite right, so wondering if it's possible or not. The idea is to export an array of tagged types as a C array to either a function or a variable / struct element. i.e. struct Blah { My_Array *Array; }; or in this case (Array below): #include typedef struct { int One; float Two; } Packet; void Dump (int First, int Last, Packet *Array) { printf ("Dump (%d .. %d)\n", First, Last); printf ("Array => %p\n", Array); for (int I = First; I < Last + 1; I++) { printf ("\tOne => %d\n", Array[I].One); printf ("\tTwo => %f\n", Array[I].Two); } } So, I tried a few things, including Holders, which I never knew existed, but this is where I am currently: with Interfaces.C; -- with Ada.Containers.Bounded_Holders; with System; package Datums is package C renames Interfaces.C; -- Force a size, we kind of want a variant like array of records, but with unknown element types, but always of -- the same number and size of elements. type Root_Packet is abstract tagged null record with Size => C.int'Size + C.C_float'Size; -- package Root_Holders is new Ada.Containers.Bounded_Holders (Element_Type => Root_Packet'Class); type Storage_Element is mod 2 ** System.Storage_Unit with Convention => C; type Storage_Array is array (Positive range <>) of Storage_Element with Convention => C; type Root_Holder is record Data : Storage_Array (1 .. Root_Packet'Max_Size_In_Storage_Elements); end record with Convention => C; type Packet_Array is array (C.size_t range <>) of aliased Root_Holder with -- Root_Holders.Holder with Convention => C; type Packet_Array_Ptr is access all Packet_Array with Convention => C; type Packet_1 is new Root_Packet with record One : C.int; Two : C.C_float; end record with Convention => C; type Packet_2 is new Root_Packet with record Banana : C.int; Mango : C.C_float; end record with Convention => C; end Datums; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Conversion; with System.Address_Image; with Datums; use Datums; procedure Testing is -- use Root_Holders; function To_Holder is new Ada.Unchecked_Conversion (Source => Packet_1, Target => Root_Holder); function To_Holder is new Ada.Unchecked_Conversion (Source => Packet_2, Target => Root_Holder); A : aliased Packet_Array := (1 => To_Holder (Packet_1'(One => 10, Two => 3.14)), 2 => To_Holder (Packet_2'(Banana => 50, Mango => 4.5))); procedure Dump (First, Last : in C.int; Data : in Packet_Array_Ptr) with Convention => C, Import => True, External_Name => "Dump"; begin Put_Line ("A'Address => " & System.Address_Image (A'Address)); Dump (C.int (A'First), C.int (A'Last), A'Unchecked_Access); end Testing; project T is for Source_Dirs use ("."); for Languages use ("C", "Ada"); for Main use ("testing.adb"); package Compiler is for Default_Switches ("Ada") use ("-g"); for Default_Switches ("C") use ("-g"); end Compiler; end T;