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