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
next prev parent 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