comp.lang.ada
 help / color / mirror / Atom feed
From: Victor Porton <porton@narod.ru>
Subject: Re: Convert between C "void*" pointer and an access
Date: Thu, 12 Oct 2017 04:01:19 +0300
Date: 2017-10-12T04:01:19+03:00	[thread overview]
Message-ID: <ormest$a63$1@gioia.aioe.org> (raw)
In-Reply-To: orm8gs$2a5$1@gioia.aioe.org

Victor Porton wrote:

> Victor Porton wrote:
> 
>> Victor Porton wrote:
>> 
>>> What is the right way to convert between C "void*" pointer and an access
>>> to a tagged or class-wide type?
>>> 
>>> Ada.Unchecked_Conversion seems to be what I need, but the access type
>>> may be "fat" and thus have another format than void*.
>>> 
>>> I caught myself doing such unchecked conversions, but now I feel I did
>>> an error.
>>> 
>>> For example, let
>>> 
>>> type X_Type is abstract tagged null record;
>>> 
>>> How to store X_Type'Class pointer in "void*" and convert them back and
>>> forth?
>> 
>> It seems I've found a right solution of my problem. (Check if Ada RM
>> warrants that it works with every compiler!)
>> 
>> Well, why it is not a standard package?! Why I need to invent something
>> "smart" every time I need to code?
> 
> The package body was with a bug. Here there is corrected code:

[snip] (see code above in the thread)

Now I will prove that it works without errors with every conforming 
compilers.

The below will describe how my package Convert_Void works. If in doubt, 
consult the package source code.

First I should formulate the problem exactly:

Having an Ada object (we can restrict to tagged and class-wide types and 
benefit from the fact that such objects 'Address "should produce a useful 
result" (RM 13.3.16)), we need to transform it to C void pointer and pass to 
C code; the C code should be able to call Ada code (e.g. through subprogram 
access) and pass the pointer back and the Ada code should be able to work 
with the original Ada object.

In other words, we need to define two functions: To_Pointer which converts 
all access values for a certain type (tagged or class-wide, at least) into 
void pointers and To_Access which converts void pointers obtained by 
To_Pointer back into the original access value.

In other words, we need two mutually inverse bijections between every set of 
values of 'Unchecked_Access of values of a type (tagged or class-wide, at 
least) and a subset of C void pointers.

We also need map null access to NULL pointer and vice versa.

We will use chars_ptr from Interfaces.C.Strings to represent void pointers. 
It is valid because C11, 6.2.5, 28 (draft N1548): "A pointer to void shall 
have the same representation and alignment requirements as a pointer to a 
character type."

This problem is solved in my generic package Convert_Void:

-- "with" and "use" skipped
generic
    type Object(<>) is limited private;
package Convert_Void is

   package Address_Conversions is new
     System.Address_To_Access_Conversions(Object);
   
   subtype Object_Pointer is Address_Conversions.Object_Pointer;
   
   function To_Access (Void_Pointer: chars_ptr) return Object_Pointer;
   
   function To_C_Pointer (Pointer: Object_Pointer) return chars_ptr;
   
end Convert_Void;

We define in Convert_Void body:

type My_Char_Pointer is access all char with Convention=>C;
package Char_Address_Conversions is new
  System.Address_To_Access_Conversions(char);

One of the steps of implementing the functions To_Pointer and To_Access is 
to convert between chars_ptr and My_Char_Pointer. This is trivially done 
with Ada.Unchecked_Conversion because they are by definition the same C type 
char* and thus have the same representation.

So our task is reduced to conversion between My_Char_Pointer an Ada object 
access.

We do this conversion (in both directions) like:

Char_Address_Conversions.To_Pointer(Address_Conversions.To_Address(...))

Address_Conversions.To_Pointer(Char_Address_Conversions.To_Address(...))

The thing to prove is that this is an injective function from object 
pointers to My_Char_Pointer values and that backward conversion is really 
its inversion.

But it is just my understanding of "The To_Pointer and To_Address 
subprograms convert back and forth between values of types Object_Pointer 
and Address." (RM 13.7.2 5/2)

That null access are mapped into NULL pointers and vice versa is left as an 
exercise to the reader.

-- 
Victor Porton - http://portonvictor.org

      reply	other threads:[~2017-10-12  1:01 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-11 21:52 Convert between C "void*" pointer and an access Victor Porton
2017-10-11 22:32 ` Randy Brukardt
2017-10-11 23:03   ` Victor Porton
2017-10-12  7:57     ` Dmitry A. Kazakov
2017-10-12  8:05     ` Simon Wright
2017-10-29 14:50   ` David Thompson
2017-10-11 22:58 ` Victor Porton
2017-10-11 23:12   ` Victor Porton
2017-10-12  1:01     ` Victor Porton [this message]
replies disabled

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