comp.lang.ada
 help / color / mirror / Atom feed
From: "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org>
Subject: Re: A suggestion about interfacing with C
Date: Mon, 2 May 2016 12:07:05 -0700
Date: 2016-05-02T12:07:05-07:00	[thread overview]
Message-ID: <ng88a9$sil$1@dont-email.me> (raw)
In-Reply-To: <45cb9b19-b470-4649-843a-7b9f88411e6e@googlegroups.com>

On 05/02/2016 09:45 AM, mockturtle wrote:
>
> I need to interface with a C library (libnl, for using Netlink in Linux).  The library provides a "socket" represented by a struct nl_sock, but the user (the library user, that is, myself) sees only a pointer to nl_sock, since the library provides constructors, destructors and everything is needed to manipulate the socket. In a sense, the user can consider the pointer just as an "opaque handler" rather than a pointer. (I must say that my first impression of the API is definitively positive).
>
> In Ada I would like to provide a slightly thick package that hides the C type behind a, say, Netlink_Socket type that could be a record holding the pointer to nl_sock. Note that since libnl uses said pointer as an opaque handle, I just need to store the "bitstring" representing its value, in order to pass it to the C library.

The 1st question is, "How many objects of this type are there in a typical 
application?" Very often in C, you find a type like this even though it makes no 
sense to have more than one of them, because the language lacks modules. If this 
is one of those cases where there will only be one of them, then the Ada 
implementation would be a pkg providing only operations, with the C pointer 
hidden in the body.

This doesn't address your low-level question, which is

> I was wandering about the best way to implement the Ada "view"  of the pointer to nl_sock.
>
> * I could use Interfaces.C.Pointers, but it seems me an overkill since I do not need to do pointer arithmetic.  Moreover, I would need to define a record equivalento to struct nl_sock (although maybe in my case a null record could suffice)
>
> * I could convert it in C to a char* and then using Interfaces.C.Strings.  (A bit dirty, but not too much...)
>
> * I could convert it to an integer... (no, definitively too dirty)
>
> * others?

This kind of opaque pointer is very common in C libraries. Some use "void*" to 
further hide the implementation details. I think you're over thinking things 
here. I usually do something like

type C_Socket is null record;
pragma Convention (C, C_Socket);

type Socket_Ptr is access all C_Socket;
pragma Convention (C, Socket_Ptr);

If you're hiding this in the pkg body, then you're done. If you're exposing the 
type, then these would be in the private part and you'll have

type Socket [(...)] is limited private;

in the public part. Also in the private part you'd have

type Socket [(...)] is limited record
    Ptr : Socket_Ptr;
end record;

or maybe even

function New_Socket [(...)] return Socket_Ptr;
pragma Import (C, New_Socket, ...);

type Socket [(...)] is limited record
    Ptr : Socket_Ptr := New_Socket [(...)];
end record;

Of course, if finalization is needed, this becomes a little more complex, as 
does initialization that needs parameters that can't be discriminants.

-- 
Jeff Carter
"When Roman engineers built a bridge, they had to stand under it
while the first legion marched across. If programmers today
worked under similar ground rules, they might well find
themselves getting much more interested in Ada!"
Robert Dewar
62


  parent reply	other threads:[~2016-05-02 19:07 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-02 16:45 A suggestion about interfacing with C mockturtle
2016-05-02 18:46 ` Simon Wright
2016-05-02 19:07 ` Jeffrey R. Carter [this message]
2016-05-02 19:40 ` Per Sandberg
2016-05-02 20:14 ` Maciej Sobczak
2016-05-03 21:53 ` mockturtle
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox