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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no 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!news4.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: "Alex R. Mosteo" Newsgroups: comp.lang.ada Subject: Re: Interfacing to C: big structures Date: Tue, 26 Feb 2008 13:00:28 +0100 Message-ID: <62idb0F23ddfnU1@mid.individual.net> References: Reply-To: alejandro@mosteo.com Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Trace: individual.net y6Z0Xj84dPkQua2izbXNRQgJytc/oxDaEeARkNpB2w9NmscZs= Cancel-Lock: sha1:7FjODPdiffk4OoB5sJ+GSmmoKfw= User-Agent: Thunderbird 2.0.0.6 (X11/20071022) In-Reply-To: Xref: g2news1.google.com comp.lang.ada:20082 Date: 2008-02-26T13:00:28+01:00 List-Id: 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. [1] http://sourceforge.net/projects/ada-player