comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: [Revisited] How to get around "access type must not be outside generic unit"
Date: Wed, 24 Jan 2007 12:42:21 +0100
Date: 2007-01-24T12:42:21+01:00	[thread overview]
Message-ID: <1u2mhr9ypij4u.bn3yayn7o9l3$.dlg@40tude.net> (raw)
In-Reply-To: WcKdnWhWUJc0MyvYnZ2dnUVZ_rKvnZ2d@megapath.net

On Tue, 23 Jan 2007 18:57:33 -0600, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:3vwf1b4b2ntl$.l9n17zmh9v8a$.dlg@40tude.net...
> ...
>> This is a quite frequent pattern which now is broken, for a good reason
>> BTW, because it was unsafe. Obviously Register cannot be touched.
> 
> Well, the best solution is to touch Register, and give it an anonymous
> access type parameter (which doesn't do accessibility checks). Even better
> is to avoid C interfacing. ;-)

Let's take GtkAda as an example. The facts are:

1. It interfaces GTK+ (C++)
2. It is full of this

package Glib is
   ...
   type Boxed_Copy is access
      function (Boxed : System.Address) return System.Address;
   pragma Convention (C, Boxed_Copy);
   type Boxed_Free is access procedure (Boxed : System.Address);
   pragma Convention (C, Boxed_Free);

   function Boxed_Type_Register_Static
     (Name : String;
      Copy : Boxed_Copy;
      Free : Boxed_Free) return GType;

How can I (well, ACT (:-)) apply Convention (C,...) on an anonymous access
type?!

> That won't work in a compiler that does generic code sharing (like
> Janus/Ada). Subprograms in a generic have an extra hidden parameter to carry
> the instance descriptor, and thus the profile doesn't match that of a
> routine outside of a generic. There is absoletely no way to change this
> inside of the generic body short of completely abandoning the code sharing
> model.

And what Janus/Ada would do if it meets pragma Convention (C, Foo); ?

>> Potential solution:
>> ------------------------
>> 1. Drop all accessibility checks for access to subprogram with
>>
>>    pragma Convention (C, ...).
>>
>>    Rationale: C subprograms are global
> 
> Won't work in a generic code shared body. Also, it would cause problems if
> your C routine written in Ada did up-level accesses - you'd have all of the
> dangling pointer issues and no checks to prevent them. C routines absolutely
> have to be written at the library level.

>> 2. Prohibit pragma Convention (C, ...) in generic bodies for any subprogram
>> types not mentioned in the specification AND in all local scopes.
> 
> That's already effectively true, since you can't do anything useful with it.
> But I don't know how this helps solve your problem.
> 
>> 3. Prohibit instantiation of generic units with pragma Convention (C, ...)
>> used in specifications otherwise as at the library level.
>>
>> The result should be the package Usage required to be instantiated on
>> library level, with Install exposed in the specification of. Explicit
>> pragma Convention (C, ...) in the specification would reject instantiations
>> without looking into bodies.
> 
> There isn't any reason to do this. It is trivial to write the specification
> of a generic so that it can only be instantiated at the library level.

I meant (1 and 2 and 3), not (1 or 2 or 3)!  (:-))

> But in any case, the solution to your problem (as always) is to put the
> 'Access into the private part of the specification. Do that with an
> appropriate constant declaration. (If the parameter type of Register was
> anonymous, there is no problem, so there must be a named type that can be
> used.) Doing so will force the generic to be instantiated at the library
> level.

OK, that's definitely better than Unchecked_Conversion. In Ada 95 it was
enough to add a declaration of the subprogram to the specification, now we
also need an access object. This is strange, at least not obvious. Why
should it change anything? I mean, if it is semantically correct, then why
the compiler cannot deduce it? Is it semantically correct? In the case with
Glib above, would it be possible to instantiate a generic package in a
local scope; call to Boxed_Type_Register_Static passing a constant as you
described; and then leave the scope?

generic
package Foo is
   ...
private
   function Copy (Boxed : System.Address) return System.Address;
   pragma Convention (C, Copy);
   procedure Free (Boxed : System.Address);
   pragma Convention (C, Free);

   Copy_Ptr : constant Boxed_Copy := Copy'Access;
   Free_Ptr : constant Boxed_Free := Free'Access;
end Foo;

package body Foo is
   function Copy (Boxed : System.Address) return System.Address is ...
   procedure Free (Boxed : System.Address) is ...
   ...
begin
   ... := Boxed_Type_Register_Static ("Foo", Copy_Ptr, Free_Ptr);
end Foo;
...

declare
   My_Foo is new Foo; -- Is it legal in Ada 2005?
begin
   ...
end; -- Boom!

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



  reply	other threads:[~2007-01-24 11:42 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-17 10:07 How to get around "access type must not be outside generic unit" Michael Erdmann
2006-12-17 12:45 ` Pascal Obry
2006-12-17 14:28   ` Michael Erdmann
2006-12-17 15:53     ` Pascal Obry
2006-12-17 20:49     ` Robert A Duff
2006-12-18  3:35   ` Brian May
2006-12-18  7:49     ` Jean-Pierre Rosen
2006-12-18 23:15       ` Brian May
2006-12-19  1:48         ` Randy Brukardt
2006-12-19  7:41         ` Jean-Pierre Rosen
2006-12-18 20:32     ` Michael Erdmann
2006-12-18 20:57       ` Randy Brukardt
2007-01-23 18:18 ` [Revisited] How to get around "access type must not be outside generic unit" (was: How to get around "access type must not be outside generic unit") Dmitry A. Kazakov
2007-01-24  0:57   ` Randy Brukardt
2007-01-24 11:42     ` Dmitry A. Kazakov [this message]
2007-01-24 11:58       ` [Revisited] How to get around "access type must not be outside generic unit" Ludovic Brenta
2007-01-24 13:46         ` Dmitry A. Kazakov
2007-01-24 20:50       ` Randy Brukardt
2007-01-25 11:07         ` Dmitry A. Kazakov
replies disabled

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