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 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!feeder.eternal-september.org!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: differences between Ada and C in gnat forcing me to use C instead of Ada Date: Mon, 25 Mar 2019 19:38:12 +0200 Organization: Tidorum Ltd Message-ID: References: <2afba838-16fd-4d5b-906a-b9cd1d864ce6@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net 5lXMkkFNf6w0nShdAADENwGDUB0EbI9bmL0p/d6sZGe2Iw8d7d Cancel-Lock: sha1:AHb7PU8IbLZCqVjXsaqy/73NGBU= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 In-Reply-To: <2afba838-16fd-4d5b-906a-b9cd1d864ce6@googlegroups.com> Xref: reader01.eternal-september.org comp.lang.ada:55959 Date: 2019-03-25T19:38:12+02:00 List-Id: On 19-03-25 16:09 , matthewbrentmccarty@gmail.com wrote: > Hi all: ... > For some reason when I call sane_get_devices as in: > > type Sane_Device_Ptr is access all sane_sane_h.SANE_Device; > for Sane_Device_Ptr'Size use Standard'Address_Size; > pragma Convention (C, Sane_Device_Ptr); > > type Device_Array is array (Integer range <>) of aliased Sane_Device_Ptr; > pragma Convention (C, Device_Array); > ... > devices : aliased Device_Array (1..5); > Status := sane_sane_h.sane_get_devices (devices(1)'Address, sane_sane_h.SANE_Bool(SANE_TRUE)); I think the Ada profile of sane_get_devices, above, is wrong. See below. > I get back garbage but in C, it works. Later, on 19-03-25 18:42 , matthewbrentmccarty@gmail.com wrote: > Hi all: ... > In my C example which works, I have a header that says: > > #define NELEMS(x) (sizeof(x) / sizeof((x)[0])) > void sane_print_devices (const SANE_Device ** device_list); > > > and then C code which does the following: > > const SANE_Device **device_list; > > status = sane_get_devices (&device_list, SANE_TRUE); which agrees with the profile for sane_get_devices quoted later in that message: > SANE_Status sane_get_devices (const SANE_Device *** device_list, > SANE_Bool local_only); In that profile, the device_list parameter is a pointer to a pointer to a pointer to a device_list (three *'s). The Ada code has only two pointer levels, so a conflict. From the description of sane_get_devices, also quoted in that message: > If the function executes successfully, it stores a pointer to > a NULL terminated array of pointers to SANE_Device structures > in *device_list. This shows that the device_list is logically an "out" parameter, that the value returned is a pointer to an array of pointers to device records, and that the responsibility for allocating the array of pointers to the device records (as well as the device records themselves) lies with the SANE library, not with the client. This also answers Dmitry's question on how the client knows the number of devices returned: the array (to which a pointer is returned) has a null pointer at its end. The Ada code should be something like this (not compiled nor tested, with representations omitted): type Sane_Device_Ptr is access all sane_sane_h.SANE_Device; type Device_Array is array (Integer range 1 .. 500) of aliased Sane_Device_Ptr; -- Constrained so as to avoid any problems with bounds dope. -- The actual array constructed in sane_get_devices may be shorter -- or longer. -- If there are less than 500 devices, the actual array ends with -- a null pointer at some index <= 500. -- If there are over 500 devices, the terminating null pointer will -- not be present. type Device_Array_Ptr is access all Device_Array; ... devices : Device_Array_Ptr; Status := sane_sane_h.sane_get_devices ( device_list => Device_Array_Ptr, local_only => sane_sane_h.SANE_Bool(SANE_TRUE)); Here I have assumed that the device_list parameter is declared in the Ada profile of sane_get_devices as "out Device_Array_Ptr", which (with the C convention) provides pass by reference (and gives the third level of pointers). HTH... -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .