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=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,c9bb37a1fdd0d3e9 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Received: by 10.68.231.138 with SMTP id tg10mr122167pbc.7.1333137468102; Fri, 30 Mar 2012 12:57:48 -0700 (PDT) MIME-Version: 1.0 Path: z9ni19779pbe.0!nntp.google.com!news2.google.com!news4.google.com!feeder2.cambriumusenet.nl!feeder1.cambriumusenet.nl!feed.tweaknews.nl!194.134.4.91.MISMATCH!news2.euro.net!newsfeed.x-privat.org!news.jacob-sparre.dk!munin.jacob-sparre.dk!pnx.dk!.POSTED!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Passing C-style flags to C subprograms Date: Fri, 30 Mar 2012 14:57:40 -0500 Organization: Jacob Sparre Andersen Research & Innovation Message-ID: References: NNTP-Posting-Host: static-69-95-181-76.mad.choiceone.net X-Trace: munin.nbi.dk 1333137465 30696 69.95.181.76 (30 Mar 2012 19:57:45 GMT) X-Complaints-To: news@jacob-sparre.dk NNTP-Posting-Date: Fri, 30 Mar 2012 19:57:45 +0000 (UTC) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5931 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6157 Date: 2012-03-30T14:57:40-05:00 List-Id: "Natasha Kerensikova" wrote in message news:slrnjnbu7o.1lme.lithiumcat@sigil.instinctive.eu... > I have been trying to write an Ada binding to libevent2. There are all > sorts of issues and I have only started, so I'm not sure it will ever > lead to anything interesting, except for my own personal enlightenment. > One of these issues is passing and retrieving "C-style" flags, and I > would love to see sharing of insights on this topic. ... > I found a solution in Florist. I don't whether it's specific to Florist > or standard (I haven't been able to find a reference for POSIX for Ada). > It defines a private Option_Set type, which is actually a modular > integer, and operations on it implemented as bitwise arithmetic. ... This is essentilly what Claw does for (most) Windows flags. ... > On the other hand, while experimenting with my bindings, I came up with > a completely different approach, based on record of booleans and > representation clauses, so that it can be passed-by-copy and be > interpreted correctly as an integer. ... We considered this and used it for a few sets of flags in Claw, but didn't do this in general for a number of reasons: (1) We needed the flag sets to be extensible without reprogramming. That is, if Microsoft adds a new flag value, we want people to be able to use it even before Claw is modified to add the flag. That works well with a numeric solution (just add a new constant); it doesn't work at all with a bit solution (unused bits stay unused). (2) Not all of the flag sets are pure bit-maps. Some include combinations so that one bit doesn't necessarily represent one flag. (3) Ada doesn't have defaults for aggregates; every component has to be mentioned (or an others clause used). That means that the aggregates representing flags are wordy; and the use of an others clause makes them less safe against modification than typical Ada code. (It's about the same safety as the original bit-flags; it's not a detrement to using records, but it means that there is no advantage in this way, either.) That is, compare: Style => WS_Border + WS_Sizable, to Style => (WS_Border => True, WS_Sizable => True, others => False), Since uses are much more common than the set of declarations, we wanted the uses to be easier. (Note that for very commonly used flags, we broke those out and gave them their own parameters to the routines, which can be properly defaulted and thus not mentioned at all in calls.) > I find the record-based approach feels more "Ada-ish" while Florist > approach feels much more C-ish, it doesn't clutter the namespace, and it > allows for 2-value enumerations that don't map to boolean (e.g. > switching between two different modes depending on the bit value), so > I generally prefer the former. However, the declaration is much bulkier > and uglier and there is no code reuse. Right. As noted above, however, the declaration is close to irrelevant; the real issue is that the *uses* are much bulkier. > However, a much more pressing question is: does the record-based > approach actually work? Yes, assuming appropriate representation clauses. Either that or your compiler should reject it (but that won't happen for typical cases). > The fact that it run successfully on my machine does not mean it would > run successfully anywhere else. Even worse, it might run but silently > produce incorrect results. > > If I understand the RM correctly, it is guaranteed that > Boolean'Pos (False) = 0 and Boolean'Pos (True) = 1. > But does that mean a 1-bit representation of a boolean necessarily match > the position value? > Should I add some representation clauses somewhere to fix that? The representation of an enumeration is the same as the position numbers unless you specify otherwise. This is a requirement -- see 13.4(8). > Can I trust the extended range of the last flag to not cause any > trouble? (I used it rather than "range 2 .. 2" to avoid a GNAT warning, > and it seemed less ugly than a pragma Warnings or bother the client with > an explicit padding field). I think it is OK, but I've always used a padding field in such records. The main reason being that when the next version of the underlying thing comes out with two new flags, you won't have a problem with invalid codes in that field. (This matters a lot if you can read these flags as well as set them, as in Windows.) > Could endianness break the solution? (I understood that that "at 0" part > avoids it by looking at bit rank in a machine word, so with the same > mapping as a C int, but I might be wrong). Endianness only matters for items larger than a byte, so for most simple flags it's irrelevant. Moreover, endianness only matters if you need to do something that has to work on a machine with different endianness than the one you are running on. (The default bit numbering works "properly" on either endianness so long as the endianness is the same for all uses of the type, as it will be in a single program.) [But note, I've never done this on a big-endian machine, so there may be some issue that I've missed.] > Are there any other issues I have missed? Not that I know of. Randy.