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,8ecbc35ea893182f X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news2.google.com!postnews.google.com!i7g2000prf.googlegroups.com!not-for-mail From: Adam Beneschan Newsgroups: comp.lang.ada Subject: Re: Interfacing to C: big structures Date: Tue, 26 Feb 2008 09:35:53 -0800 (PST) Organization: http://groups.google.com Message-ID: <56a177e4-506f-4bc8-a531-7f2dd15d50c8@i7g2000prf.googlegroups.com> References: <62idb0F23ddfnU1@mid.individual.net> NNTP-Posting-Host: 66.126.103.122 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: posting.google.com 1204047353 11149 127.0.0.1 (26 Feb 2008 17:35:53 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Tue, 26 Feb 2008 17:35:53 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: i7g2000prf.googlegroups.com; posting-host=66.126.103.122; posting-account=duW0ogkAAABjRdnxgLGXDfna0Gc6XqmQ User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.12) Gecko/20050922 Fedora/1.7.12-1.3.1,gzip(gfe),gzip(gfe) Xref: g2news1.google.com comp.lang.ada:20097 Date: 2008-02-26T09:35:53-08:00 List-Id: On Feb 26, 4:00 am, "Alex R. Mosteo" wrote: > Maciej Sobczak wrote: > > Hi, > > > Consider the C API that contains some structure S and a couple of > > functions that operate on the state that is stored in the Struct. A > > typical usage in C might be: > > > struct S s; > > > init(&s); > > foo(&s); > > bar(&s); > > baz(&s); > > > Above, s is created with automatic storage duration. > > > How to interface to this from Ada? I see two options: > > > 1. Write a simple wrapper that will create S on the heap and use the > > pointer everywhere. This is easy, but imposes the use of dynamic > > memory, which for some reasons I might want to avoid. > > 2. Create an Ada array of basic storage units of "appropriate size" > > and pass its address to the C functions. The advantage of this > > solution is that it does not impose any particular memory management > > scheme, but the disadvantage is that it is potentially non-portable > > (how to get the "appropriate size"?). > > > Would you suggest some other solution? > > I have used this trick for types in C that I don't want to replicate in > Ada with pragma convention C, and that adds the bonus of being always in > sync with the C part, even if it changes, by means of a single > recompiling. You can see examples of use in my ada-player binding [1]: > > The following is not compiled, there may be mistakes. Hope you get the idea. > > 1. Create a C helper file with > > size_t size_of_S(void) { return sizeof (struct S); }; > > and a corresponding helper binding in Ada: > > function Size_Of_S return Interfaces.C.Size_T; > pragma Import (Size_Of_S, "size_of_S"); > > 2. Create an Ada type as > > type S is new Ada.Streams.Stream_Element_Array > (1 .. Stream_Offset (Size_Of_S)); > pragma Pack (S); -- Not sure if this is even needed. > > Note that this type gets its size at elaboration time, and thus this is > what fixes this type if the C corresponding struct changes. > > 3. Use the S Ada type through binding functions to the C functions. In > practice, you have a byte receptacle in the Ada side, and that's all. > You retain the use in the stack and through the C API. I find this very > practical for well-designed C libraries where all usage is through > functions with client-opaque types, since it requires zero maintenance > if the C type changes. I thought of something like this, but Maciej said something about wanting to avoid dynamic memory, and it seems that you're defining a type whose size isn't going to be known until runtime, and therefore if you declare an Ada variable of that type, it will have to be allocated dynamically in some way. Maybe the particular way it would be done is acceptable to Maciej, though (a local variable could be allocated simply by moving the stack pointer, depending on the implementation). Anyway, this seems like the best way to do things if it isn't unacceptable for that reason. -- Adam