comp.lang.ada
 help / color / mirror / Atom feed
* System.Address to Access to function/procedure conversion
@ 2013-07-28 15:27 Tarek Ghaleb
  2013-07-28 16:14 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Tarek Ghaleb @ 2013-07-28 15:27 UTC (permalink / raw)


Hi Everyone,

This is my first post to comp.lang.ada and it is so embarrassingly
trivial. Given an Address of a function/procedure, how can you call it
or convert the address to an access?

I first thought of System.Address_To_Access_Conversions, but then it
doesn't seem to work for a function/procedure.

The way I finally did it was to wrap an access to the function in a
record and then pass the Address of the record, but there must be a
simpler way.

As for why not just pass an Access to the function directly, the
Address is actually passed to a C function which later passes it back
to Ada.

Tarek.

-- 
For fools rush in where angels fear to tread. -- Alexander Pope

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 15:27 System.Address to Access to function/procedure conversion Tarek Ghaleb
@ 2013-07-28 16:14 ` Dmitry A. Kazakov
  2013-07-28 19:05   ` Tarek Ghaleb
  2013-07-28 17:19 ` Jeffrey Carter
  2013-07-28 21:31 ` Maciej Sobczak
  2 siblings, 1 reply; 15+ messages in thread
From: Dmitry A. Kazakov @ 2013-07-28 16:14 UTC (permalink / raw)


On Sun, 28 Jul 2013 15:27:48 +0000 (UTC), Tarek Ghaleb wrote:

> As for why not just pass an Access to the function directly, the
> Address is actually passed to a C function which later passes it back
> to Ada.

If you pass anything to C you should better keep it under C convention,
even if you are certain that C does not touch it. You should pass an
access-to-procedure/function to C and get it back. The access type will
have pragma Convention (C, ... set. You don't need address here. E.g.

   type Func is access procedure (...);
   pragma Convention (C, Func);

   procedure C_Stuff (...; Call_Back_Ptr : Func; ...);
   pragma Import (C, C_Stuff, "fancy_c_library_entry");

The rationale is that, maybe unlikely still the access type might have a
different size than address and/or C pointer. When you use pragma
Convention (or the corresponding aspect if in Ada 2012) it is guaranteed to
work.

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 15:27 System.Address to Access to function/procedure conversion Tarek Ghaleb
  2013-07-28 16:14 ` Dmitry A. Kazakov
@ 2013-07-28 17:19 ` Jeffrey Carter
  2013-07-28 19:05   ` Tarek Ghaleb
  2013-07-28 21:31 ` Maciej Sobczak
  2 siblings, 1 reply; 15+ messages in thread
From: Jeffrey Carter @ 2013-07-28 17:19 UTC (permalink / raw)


On 07/28/2013 08:27 AM, Tarek Ghaleb wrote:
>
> As for why not just pass an Access to the function directly, the
> Address is actually passed to a C function which later passes it back
> to Ada.

If you want any semblance of portability, then you should never pass an Address 
to C. You should only pass a C-convention access type. The value must be stored 
as a pointer on the C side, and there is no guarantee that Ada's Address has any 
relationship to a C pointer. A C-convention access type, on the other hand, is 
guaranteed to make sense as a C pointer.

-- 
Jeff Carter
"Oh Lord, bless this thy hand grenade, that with it thou
mayst blow thine enemies to tiny bits, in thy mercy."
Monty Python and the Holy Grail
24

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 16:14 ` Dmitry A. Kazakov
@ 2013-07-28 19:05   ` Tarek Ghaleb
  2013-07-28 19:23     ` Simon Wright
                       ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Tarek Ghaleb @ 2013-07-28 19:05 UTC (permalink / raw)


On 2013-07-28, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
> If you pass anything to C you should better keep it under C convention,
> even if you are certain that C does not touch it. You should pass an
> access-to-procedure/function to C and get it back. The access type will
> have pragma Convention (C, ... set. You don't need address here. E.g.

I agree completely. Using C convention is the way to do it. But is it
*possible* to call a function using its address? (even if not a such a
great idea)

But let me explain how this question came about:

I've been experimenting with writing a thick binding for FLTK for a
couple of days now, just exploring the idea (which deserves a thread
by itself, since it would be interesting to get some
feedback). Anyway, one thing I started working on was callbacks, If I
use C convention the user of the binding will also have to declare his
procedure using C convention. For example (simplified)

  procedure Cb_Button;
  pragma Convention (C, Cb_Button);  -- This is required I guess

and then later register the callback with

  Btn.Callback(Cb_Button'Access);

But if I remove 

  pragma Conversion (C, Cb_Button);

I get 

  ...: subprogram "Cb_Button" has wrong convention
  ...: does not match convention of access type

But I don't want the user to worry about using pragma Convention for
every defined callback procedure or think in terms of interfacing with
C (or in FLTK's case C++). Ideally, Callback() is not the actual
imported callback() but it takes Ada friendly parameters and does any
type conversions needed then calls the imported callback() function. I
thought maybe it works like above but without the convention line and
then Callback() would send the Address instead of the Access to the
actual callback(). But maybe there is a better way to do it.

There are other issues of course, for example: callbacks do take
parameters and some are void* but that would complicate my question
for the time being.

Tarek.

-- 
For fools rush in where angels fear to tread. -- Alexander Pope

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 17:19 ` Jeffrey Carter
@ 2013-07-28 19:05   ` Tarek Ghaleb
  2013-07-28 20:04     ` Jeffrey Carter
  0 siblings, 1 reply; 15+ messages in thread
From: Tarek Ghaleb @ 2013-07-28 19:05 UTC (permalink / raw)


On 2013-07-28, Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> wrote:
> If you want any semblance of portability, then you should never pass
> an Address to C. You should only pass a C-convention access type.

I agree, it is a much cleaner and portable way to do it.

> ... there is no guarantee that Ada's Address has any relationship to
> a C pointer.

Interesting, I thought System.Address was equivalent to a C pointer,
and I've seen it used that way in many snippets of code, etc. For
things like void*, if not represented as System.Address, how would it
be represented then?

Tarek.

-- 
For fools rush in where angels fear to tread. -- Alexander Pope

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 19:05   ` Tarek Ghaleb
@ 2013-07-28 19:23     ` Simon Wright
  2013-07-28 22:03       ` Tarek Ghaleb
  2013-07-28 20:03     ` Dmitry A. Kazakov
  2013-07-28 21:13     ` Shark8
  2 siblings, 1 reply; 15+ messages in thread
From: Simon Wright @ 2013-07-28 19:23 UTC (permalink / raw)


Tarek Ghaleb <invalid@invalid.org> writes:

> Ideally, Callback() is not the actual imported callback() but it takes
> Ada friendly parameters and does any type conversions needed then
> calls the imported callback() function.

I find this confusing because I'm used to thinking of the procedure-to-
be-called-back as the 'callback', and what you're talking about here is
the registration interface. But if that's FLTK's nomenclature ...

Especially if the called-back procedure takes parameters, you're going
to have to do a conversion on the way back as well! I think you might be
able to do something with a generic, but .. you can't make a generic
formal type definition that declares an "access to procedure with this
parameter profile" type.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 19:05   ` Tarek Ghaleb
  2013-07-28 19:23     ` Simon Wright
@ 2013-07-28 20:03     ` Dmitry A. Kazakov
  2013-07-28 21:13     ` Shark8
  2 siblings, 0 replies; 15+ messages in thread
From: Dmitry A. Kazakov @ 2013-07-28 20:03 UTC (permalink / raw)


On Sun, 28 Jul 2013 19:05:44 +0000 (UTC), Tarek Ghaleb wrote:

> On 2013-07-28, Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>> If you pass anything to C you should better keep it under C convention,
>> even if you are certain that C does not touch it. You should pass an
>> access-to-procedure/function to C and get it back. The access type will
>> have pragma Convention (C, ... set. You don't need address here. E.g.
> 
> I agree completely. Using C convention is the way to do it. But is it
> *possible* to call a function using its address? (even if not a such a
> great idea)
> 
> But let me explain how this question came about:
> 
> I've been experimenting with writing a thick binding for FLTK for a
> couple of days now, just exploring the idea (which deserves a thread
> by itself, since it would be interesting to get some
> feedback). Anyway, one thing I started working on was callbacks, If I
> use C convention the user of the binding will also have to declare his
> procedure using C convention. For example (simplified)
> 
>   procedure Cb_Button;
>   pragma Convention (C, Cb_Button);  -- This is required I guess
> 
> and then later register the callback with
> 
>   Btn.Callback(Cb_Button'Access);
> 
> But if I remove 
> 
>   pragma Conversion (C, Cb_Button);
> 
> I get 
> 
>   ...: subprogram "Cb_Button" has wrong convention
>   ...: does not match convention of access type
> 
> But I don't want the user to worry about using pragma Convention for
> every defined callback procedure or think in terms of interfacing with
> C (or in FLTK's case C++). Ideally, Callback() is not the actual
> imported callback() but it takes Ada friendly parameters and does any
> type conversions needed then calls the imported callback() function. I
> thought maybe it works like above but without the convention line and
> then Callback() would send the Address instead of the Access to the
> actual callback(). But maybe there is a better way to do it.

Usually C bindings pass an internal procedure of C convention. The user
provided callback is called from there. From my POV it is too low level for
good bindings. I prefer primitive operations of a tagged type instead of
using a raw subprogram. E.g. an interface with the operation Clicked passed
to button's On_Click.

   type Button_Interface is limited interface;
   procedure Clicked (Handler : in out Button_Interface;
      Issuer : Widget'Class) is abstract;

   type Button is ...
   procedure On_Click (Widget : in out Button;
      Handler : not null access Button_Interface'Class);  -- [*]

Normally C library call takes an additional parameter void* passed as a
"User_Data" argument etc. Almost all C libraries provide such user data
arguments. This is a way to marshal parameters to the C callback from where
you call an Ada subprogram or dispatch.

Depending on what is the recipient of the callback you choose the strategy
of marshaling data through void*. A typical way for a widget library is
that when you connect to a signal emitted by a widget, a reference counted
object is allocated by the C library. The library deletes the object when
the signal gets disconnected or when the widget is destroyed. This object
is directly or indirectly pointed by the User_Data argument. There are
various issues when which object gets deallocated, which is not simple
stuff, but almost always necessary because user parameters never fit into
single void* argument.

When no user data argument is supported, you would use so-called
"trampolines", which is of course quite nasty stuff.

-------------
*  You would like to wrap Button_Interface into a smart pointer object and
use the latter in On_Click.

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 19:05   ` Tarek Ghaleb
@ 2013-07-28 20:04     ` Jeffrey Carter
  0 siblings, 0 replies; 15+ messages in thread
From: Jeffrey Carter @ 2013-07-28 20:04 UTC (permalink / raw)


On 07/28/2013 12:05 PM, Tarek Ghaleb wrote:
>
> Interesting, I thought System.Address was equivalent to a C pointer,
> and I've seen it used that way in many snippets of code, etc. For
> things like void*, if not represented as System.Address, how would it
> be represented then?

Such code is compiler-dependent. GNAT usually (always?) maintains a 
correspondence between hardware address, System.Address, access types, and C 
pointers, but I've certainly used compilers where that wasn't true. I recall one 
system written originally with GNAT that was ported to Rational (same platform). 
The code used Unchecked_Conversion between access types and System.Address, 
which failed miserably on Rational, where the 2 were not the same. It had to be 
revised to use System.Address_To_Access_Conversions, which was not a trivial 
undertaking. Moral: it's usually cheaper to write portable code in the 1st place.

A void* passed between C and Ada is usually C's equivalent of a private type, 
with all values coming from C and never dereferenced by Ada. For such cases, all 
that we need to model in Ada is that what we have is a C pointer. The 
implementation usually looks like

type Void is null record;
type Void_Ptr is access all Void;
pragma Convention (C, Void_Ptr);

Of course, there's no real need for type Void; Void_Ptr could be "access all 
Integer" and it would work just as well. The advantage of using Void is that 
anyone who dereferences a Void_Ptr gets something useless.

If Void_Ptr is declared publicly, it should obviously be [limited] private. And 
usually there's a better name for it than Void_Ptr.

-- 
Jeff Carter
"Oh Lord, bless this thy hand grenade, that with it thou
mayst blow thine enemies to tiny bits, in thy mercy."
Monty Python and the Holy Grail
24

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 19:05   ` Tarek Ghaleb
  2013-07-28 19:23     ` Simon Wright
  2013-07-28 20:03     ` Dmitry A. Kazakov
@ 2013-07-28 21:13     ` Shark8
  2013-07-28 22:54       ` Tarek Ghaleb
  2 siblings, 1 reply; 15+ messages in thread
From: Shark8 @ 2013-07-28 21:13 UTC (permalink / raw)


On Sunday, July 28, 2013 1:05:44 PM UTC-6, Tarek Ghaleb wrote:
> On 2013-07-28, Dmitry A. Kazakov wrote:
> 
> > If you pass anything to C you should better keep it under C convention,
> > even if you are certain that C does not touch it. You should pass an
> > access-to-procedure/function to C and get it back. The access type will
> > have pragma Convention (C, ... set. You don't need address here. E.g.
> 
> I agree completely. Using C convention is the way to do it. But is it
> *possible* to call a function using its address? (even if not a such a
> great idea)

Yes. It's actually absurdly easy. Here's a sample of how to do it in Ada 2012, the same will work in earliet versions of Ada using Pargmas... all the way back to 83, IIUC.

    -- Used a declare-block for expedience; I had a test-bed file open.
    -- Be sure to WITH System.

    ACTUAL_TEST:
    declare

	Procedure K with Convention => C;
	Procedure K is
	begin
	    Ada.Text_IO.Put_Line( "K was called" );
	end K;
	
	Procedure Execute( Addr : System.Address ) is
	    Procedure Stub with Import, Convention => C, Address => Addr;
	Begin
	    Stub;
	End Execute;
	
    begin
	Execute( K'Address );
    end ACTUAL_TEST; 

And there you are.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 15:27 System.Address to Access to function/procedure conversion Tarek Ghaleb
  2013-07-28 16:14 ` Dmitry A. Kazakov
  2013-07-28 17:19 ` Jeffrey Carter
@ 2013-07-28 21:31 ` Maciej Sobczak
  2013-07-29  6:26   ` Tarek Ghaleb
  2 siblings, 1 reply; 15+ messages in thread
From: Maciej Sobczak @ 2013-07-28 21:31 UTC (permalink / raw)


> Given an Address of a function/procedure, how can you call it
> or convert the address to an access?

This article can be helpful:

http://www.inspirel.com/articles/Polymorphic_Callbacks_Ada_Cpp.html

The article goes even further than what you describe, as it shows polymorphic (object-oriented) callbacks, so in your case the actual solution might be one or two details simpler. In any case, it uses System.Address and standard Ada conversions to do the work.

-- 
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 19:23     ` Simon Wright
@ 2013-07-28 22:03       ` Tarek Ghaleb
  0 siblings, 0 replies; 15+ messages in thread
From: Tarek Ghaleb @ 2013-07-28 22:03 UTC (permalink / raw)


On 2013-07-28, Simon Wright <simon@pushface.org> wrote:
> Tarek Ghaleb <invalid@invalid.org> writes:
>
>> Ideally, Callback() is not the actual imported callback() but it takes
>> Ada friendly parameters and does any type conversions needed then
>> calls the imported callback() function.
>
> I find this confusing because I'm used to thinking of the procedure-to-
> be-called-back as the 'callback', and what you're talking about here is
> the registration interface. But if that's FLTK's nomenclature ...

Yes, this is the naming for FLTK, but I can change that I guess. I
probably should have used a different name here for clarity, Register()
perhaps or Register_Callback().

> Especially if the called-back procedure takes parameters, you're going
> to have to do a conversion on the way back as well!

Initially, I thought it was simple, but now it doesn't seem so easy
:-) I'd want to wrap the user callback, Button_Cb() for example, in
another procedure that fits the profile required by the imported
callback registration function and does that conversion and calling of
Button_Cb().

One idea of the Registration procedure, stripped down and not
considering parameters and parameter conversion (but saves the user
from having to use pragma Convention C) is

   procedure Register_Callback (Proc : access procedure) is

      procedure Cb_Wrapper;
      pragma Convention (C, Cb_Wrapper);

      procedure Cb_Wrapper is
      begin
         Proc.all;
      end Cb_Wrapper;
   begin
      imported_callback_registration (Cb_Wrapper'Access);
   end Register_Callback;

But this of course wouldn't work, since the Wrapper is allocated on
the stack and is deeper than access type.

> I think you might be able to do something with a generic, but .. you
> can't make a generic formal type definition that declares an "access
> to procedure with this parameter profile" type.

A generic used in which way? I'd like Register_Callback() to be
callable simply with an access to a procedure that fits a certain
profile with the caller not having to worry about details. The wrapper
could be a generic maybe. There are a couple of other ideas but
nothing promising so far.

Tarek.

-- 
The opposite of a correct statement is a false statement. But the opposite
of a profound truth may well be another profound truth. -- Niels Bohr

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 21:13     ` Shark8
@ 2013-07-28 22:54       ` Tarek Ghaleb
  2013-07-29  3:27         ` Shark8
  0 siblings, 1 reply; 15+ messages in thread
From: Tarek Ghaleb @ 2013-07-28 22:54 UTC (permalink / raw)


On 2013-07-28, Shark8 <onewingedshark@gmail.com> wrote:
>> I agree completely. Using C convention is the way to do it. But is it
>> *possible* to call a function using its address? (even if not a such a
>> great idea)

> Yes. It's actually absurdly easy. Here's a sample of how to do it in
> Ada 2012, the same will work in earliet versions of Ada using
> Pargmas... all the way back to 83, IIUC.

>     ACTUAL_TEST:
>     declare
>
> 	Procedure K with Convention => C;
> 	Procedure K is
> 	begin
> 	    Ada.Text_IO.Put_Line( "K was called" );
> 	end K;
> 	
> 	Procedure Execute( Addr : System.Address ) is
> 	    Procedure Stub with Import, Convention => C, Address => Addr;
> 	Begin
> 	    Stub;
> 	End Execute;
> 	
>     begin
> 	Execute( K'Address );
>     end ACTUAL_TEST; 

Great! I didn't know about the Address Aspect. I don't think it exists
in pragma form, though. At least I couldn't find it in the RM; but
thanks, that answers my question.

Tarek.

-- 
Aim for the moon. If you miss, you may hit a star. -- W. Clement Stone

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 22:54       ` Tarek Ghaleb
@ 2013-07-29  3:27         ` Shark8
  2013-07-29  7:06           ` Tarek Ghaleb
  0 siblings, 1 reply; 15+ messages in thread
From: Shark8 @ 2013-07-29  3:27 UTC (permalink / raw)


On Sunday, July 28, 2013 4:54:27 PM UTC-6, Tarek Ghaleb wrote:
> On 2013-07-28, Shark8 wrote:
> 
> >> I agree completely. Using C convention is the way to do it. But is it
> >> *possible* to call a function using its address? (even if not a such a
> >> great idea)
> 
> > Yes. It's actually absurdly easy. Here's a sample of how to do it in
> > Ada 2012, the same will work in earliet versions of Ada using
> > Pargmas... all the way back to 83, IIUC.

Oops; a little overzealous there.
You have to use attribute definition clauses, which IIRC came in Ada 95.
Below compiles and runs in GNAT using Ada83-mode:

--  Pragma Ada_2012;
Pragma Ada_83;
Pragma Assertion_Policy( Check );

With
Text_IO,
System;

Procedure Test is

Begin
    Text_IO.Put_Line("Starting Test:");


    ACTUAL_TEST:
    declare

	-- Note: Pragma CONVENTION is non-standard.
	Procedure K;
	Pragma Convention( C, K );
	
	Procedure K is
	begin
	    Text_IO.Put_Line( "K was called" );
	end K;
	
	Procedure Execute( Addr : System.Address ) is
	    -- Note: Pragma IMPORT is non-standard.
	    Procedure Stub;
	    Pragma Import( C, Stub );

	    -- Note: The Ada 83 LRM, 13.5 (Address Clauses) gives the following:
	    --         for CONTROL use at 16#0020#; -- assuming that SYSTEM.ADDRESS is an integer
	    --   with the following warning:
	    --    Address clauses should not be used to achieve overlays of
	    --    objects or overlays of program units. Nor should a given
	    --    interrupt be linked to more than one entry. Any program using
	    --    address clauses to achieve such effects is erroneous.      
	    --
	    --  In Ada 95 we get propper Attribute Definition Clauses and so
	    --  we would use the following:
	    --    For Stub'Address Use Addr;
	    For Stub use at Addr;

	    Use Text_IO;
	Begin
	    Put_Line( "Executing:" );
	    Put( ASCII.HT );
	    Stub;
	End Execute;
	
    begin
	Execute( K'Address );
    end ACTUAL_TEST;
    
    
    Text_IO.Put_Line("Testing complete.");
End Test;

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-28 21:31 ` Maciej Sobczak
@ 2013-07-29  6:26   ` Tarek Ghaleb
  0 siblings, 0 replies; 15+ messages in thread
From: Tarek Ghaleb @ 2013-07-29  6:26 UTC (permalink / raw)


On 2013-07-28, Maciej Sobczak <see.my.homepage@gmail.com> wrote:
>> Given an Address of a function/procedure, how can you call it
>> or convert the address to an access?

> This article can be helpful:
> http://www.inspirel.com/articles/Polymorphic_Callbacks_Ada_Cpp.html

> The article goes even further than what you describe, as it shows
> polymorphic (object-oriented) callbacks, so in your case the actual
> solution might be one or two details simpler. In any case, it uses
> System.Address and standard Ada conversions to do the work.

Yes, the article is very relevant to what I'm doing. It's very
interesting. Especially, that it's about callbacks and C++, which is
exactly what I'm dealing with. Thanks for the link.

Tarek.

-- 
Rotten wood cannot be carved. -- Confucius, "Analects", Book 5, Ch. 9

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: System.Address to Access to function/procedure conversion
  2013-07-29  3:27         ` Shark8
@ 2013-07-29  7:06           ` Tarek Ghaleb
  0 siblings, 0 replies; 15+ messages in thread
From: Tarek Ghaleb @ 2013-07-29  7:06 UTC (permalink / raw)


On 2013-07-29, Shark8 <onewingedshark@gmail.com> wrote:
> On Sunday, July 28, 2013 4:54:27 PM UTC-6, Tarek Ghaleb wrote:
>> On 2013-07-28, Shark8 wrote:
>> 
>> >> I agree completely. Using C convention is the way to do it. But is it
>> >> *possible* to call a function using its address? (even if not a such a
>> >> great idea)
>> 
>> > Yes. It's actually absurdly easy. Here's a sample of how to do it in
>> > Ada 2012, the same will work in earliet versions of Ada using
>> > Pargmas... all the way back to 83, IIUC.
>
> Oops; a little overzealous there.
> You have to use attribute definition clauses, which IIRC came in Ada 95.
> Below compiles and runs in GNAT using Ada83-mode:
>
> --  Pragma Ada_2012;
> Pragma Ada_83;
> Pragma Assertion_Policy( Check );
>
> With
> Text_IO,
> System;
>
> Procedure Test is
>
> Begin
>     Text_IO.Put_Line("Starting Test:");
>
>
>     ACTUAL_TEST:
>     declare
>
> 	-- Note: Pragma CONVENTION is non-standard.
> 	Procedure K;
> 	Pragma Convention( C, K );
> 	
> 	Procedure K is
> 	begin
> 	    Text_IO.Put_Line( "K was called" );
> 	end K;
> 	
> 	Procedure Execute( Addr : System.Address ) is
> 	    -- Note: Pragma IMPORT is non-standard.
> 	    Procedure Stub;
> 	    Pragma Import( C, Stub );
>
> 	    -- Note: The Ada 83 LRM, 13.5 (Address Clauses) gives the following:
> 	    --         for CONTROL use at 16#0020#; -- assuming that
> 	    --         SYSTEM.ADDRESS is an integer
> 	    --   with the following warning:
> 	    --    Address clauses should not be used to achieve overlays of
> 	    --    objects or overlays of program units. Nor should a given
> 	    --    interrupt be linked to more than one entry. Any program using
> 	    --    address clauses to achieve such effects is erroneous.      
>
> 	    Use Text_IO;
> 	Begin
> 	    Put_Line( "Executing:" );
> 	    Put( ASCII.HT );
> 	    Stub;
> 	End Execute;
> 	
>     begin
> 	Execute( K'Address );
>     end ACTUAL_TEST;
>     
>     
>     Text_IO.Put_Line("Testing complete.");
> End Test;

That's an _exhaustively_ thorough answer :-))

Actually, I've used 

  For A'Address Use B'Address;

before, but never thought of using it for a subprogram: the way you
showed in the example above.

Tarek.

-- 
Rotten wood cannot be carved. -- Confucius, "Analects", Book 5, Ch. 9

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2013-07-29  7:06 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-28 15:27 System.Address to Access to function/procedure conversion Tarek Ghaleb
2013-07-28 16:14 ` Dmitry A. Kazakov
2013-07-28 19:05   ` Tarek Ghaleb
2013-07-28 19:23     ` Simon Wright
2013-07-28 22:03       ` Tarek Ghaleb
2013-07-28 20:03     ` Dmitry A. Kazakov
2013-07-28 21:13     ` Shark8
2013-07-28 22:54       ` Tarek Ghaleb
2013-07-29  3:27         ` Shark8
2013-07-29  7:06           ` Tarek Ghaleb
2013-07-28 17:19 ` Jeffrey Carter
2013-07-28 19:05   ` Tarek Ghaleb
2013-07-28 20:04     ` Jeffrey Carter
2013-07-28 21:31 ` Maciej Sobczak
2013-07-29  6:26   ` Tarek Ghaleb

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