comp.lang.ada
 help / color / mirror / Atom feed
* Unchecked_Union record inside an other record - trouble
@ 2014-08-08 15:36 Victor Porton
  2014-08-08 16:01 ` Adam Beneschan
  2014-08-08 19:21 ` Per Sandberg
  0 siblings, 2 replies; 17+ messages in thread
From: Victor Porton @ 2014-08-08 15:36 UTC (permalink / raw)


I am trying to interface my program with a C library.

The below program does not compile:

main.adb:19:14: unconstrained subtype in component declaration

If this does not work, what should I do to interface a union inside a struct 
in a C library?

-- main.adb
with Interfaces.C; use Interfaces.C;

procedure Main is

   type Kind is (First, Second);
   
   type T(K: Kind) is
      record
         case K is
            when First  => I: int;
            when Second => C: char;
         end case;
      end record
   with Unchecked_Union, Convention=>C;

   type T2 is
      record
         Z: int;
         Ob: T;
      end record
   with Convention=>C;
   
begin
   null;
end;

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

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 15:36 Unchecked_Union record inside an other record - trouble Victor Porton
@ 2014-08-08 16:01 ` Adam Beneschan
  2014-08-08 16:56   ` Victor Porton
  2014-08-08 19:52   ` Victor Porton
  2014-08-08 19:21 ` Per Sandberg
  1 sibling, 2 replies; 17+ messages in thread
From: Adam Beneschan @ 2014-08-08 16:01 UTC (permalink / raw)


On Friday, August 8, 2014 8:36:48 AM UTC-7, Victor Porton wrote:
> I am trying to interface my program with a C library.

> The below program does not compile:
> main.adb:19:14: unconstrained subtype in component declaration

> If this does not work, what should I do to interface a union inside a struct 
> in a C library?

> -- main.adb
> 
> with Interfaces.C; use Interfaces.C;

> procedure Main is

>    type Kind is (First, Second);
 
>    type T(K: Kind) is

change this to

     type T(K: Kind := Kind'First) is

                                   -- Adam

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 16:01 ` Adam Beneschan
@ 2014-08-08 16:56   ` Victor Porton
  2014-08-08 18:52     ` Shark8
  2014-08-08 19:52   ` Victor Porton
  1 sibling, 1 reply; 17+ messages in thread
From: Victor Porton @ 2014-08-08 16:56 UTC (permalink / raw)


Adam Beneschan wrote:

> On Friday, August 8, 2014 8:36:48 AM UTC-7, Victor Porton wrote:
>> I am trying to interface my program with a C library.
> 
>> The below program does not compile:
>> main.adb:19:14: unconstrained subtype in component declaration
> 
>> If this does not work, what should I do to interface a union inside a
>> struct in a C library?
> 
>> -- main.adb
>> 
>> with Interfaces.C; use Interfaces.C;
> 
>> procedure Main is
> 
>>    type Kind is (First, Second);
>  
>>    type T(K: Kind) is
> 
> change this to
> 
>      type T(K: Kind := Kind'First) is

Done.

But it is a hack.

I propose to change ARM not to require a discriminant in this specific case 
(Unchecked_Union).

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


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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 16:56   ` Victor Porton
@ 2014-08-08 18:52     ` Shark8
  2014-08-08 19:56       ` Victor Porton
  0 siblings, 1 reply; 17+ messages in thread
From: Shark8 @ 2014-08-08 18:52 UTC (permalink / raw)


On 08-Aug-14 10:56, Victor Porton wrote:
>
> But it is a hack.

How are you going to be able to tell which variant the subcomponent is 
though? The C union *doesn't* tag the varying part, so that information 
has to be kept elsewhere... or ignored completely.

> I propose to change ARM not to require a discriminant in this specific case
> (Unchecked_Union).

No.
Just no.
What you propose here would import from C weak typing -- if you want 
weak typing, why re you using Ada?

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 15:36 Unchecked_Union record inside an other record - trouble Victor Porton
  2014-08-08 16:01 ` Adam Beneschan
@ 2014-08-08 19:21 ` Per Sandberg
  2014-08-08 20:01   ` Victor Porton
  2014-08-08 21:23   ` Jeffrey Carter
  1 sibling, 2 replies; 17+ messages in thread
From: Per Sandberg @ 2014-08-08 19:21 UTC (permalink / raw)


You shall not try to write interface code by hand you shall use the 
compiler
	gcc -c -fdump-ada-spec <more arguments and files>
see GNAT Users guide.

Since humans makes a heap load of errors and erronous asumptions when 
they try to translate the contents of a .h file to an .ads file, the 
compiler does a much better job.

/Per


On 08.08.2014 17:36, Victor Porton wrote:
> I am trying to interface my program with a C library.
>
> The below program does not compile:
>
> main.adb:19:14: unconstrained subtype in component declaration
>
> If this does not work, what should I do to interface a union inside a struct
> in a C library?
>
> -- main.adb
> with Interfaces.C; use Interfaces.C;
>
> procedure Main is
>
>     type Kind is (First, Second);
>
>     type T(K: Kind) is
>        record
>           case K is
>              when First  => I: int;
>              when Second => C: char;
>           end case;
>        end record
>     with Unchecked_Union, Convention=>C;
>
>     type T2 is
>        record
>           Z: int;
>           Ob: T;
>        end record
>     with Convention=>C;
>
> begin
>     null;
> end;
>


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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 16:01 ` Adam Beneschan
  2014-08-08 16:56   ` Victor Porton
@ 2014-08-08 19:52   ` Victor Porton
  2014-08-08 19:57     ` Adam Beneschan
  1 sibling, 1 reply; 17+ messages in thread
From: Victor Porton @ 2014-08-08 19:52 UTC (permalink / raw)


Adam Beneschan wrote:
> On Friday, August 8, 2014 8:36:48 AM UTC-7, Victor Porton wrote:
>> I am trying to interface my program with a C library.
> 
>> The below program does not compile:
>> main.adb:19:14: unconstrained subtype in component declaration
> 
>> If this does not work, what should I do to interface a union inside a
>> struct in a C library?
> 
>> -- main.adb
>> 
>> with Interfaces.C; use Interfaces.C;
> 
>> procedure Main is
> 
>>    type Kind is (First, Second);
>  
>>    type T(K: Kind) is
> 
> change this to
> 
>      type T(K: Kind := Kind'First) is

OK, I followed your way, Adam.

But it produces a warning with GNAT 4.9 (for the below program):

gnatmake -q -c -gnatc -u -P/home/porton/t/default.gpr main.adb --subdirs=check -cargs -g -O0 -gnato -fstack-check -gnatVa
main.adb:26:17: warning: component not present in subtype of "T" defined at line 21
main.adb:26:17: warning: "Constraint_Error" will be raised at run time

Should I just disable this warning? (BTW, how to disable this warning in
GNAT-GPS?)

It seems that there will be a "Constraint_Error" and this is really bad.

Any other idea/workarounds?

-- main.adb
with Interfaces.C; use Interfaces.C;

procedure Main is

   type Kind is (First, Second);
   
   type T(K: Kind) is
      record
         case K is
            when First =>
               X: int;
            when Second =>
               Y: char;
         end case;
      end record
      with Unchecked_Union, Convention=>C;
   
   type Container is
      record
         Z: int;
         R: T(Kind'First);
      end record;
   
   function P (C: Container) return char is
   begin
      return C.R.Y;
   end;

begin
   null;
end;


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

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 18:52     ` Shark8
@ 2014-08-08 19:56       ` Victor Porton
  2014-08-08 20:06         ` Pascal Obry
  2014-08-08 20:09         ` Shark8
  0 siblings, 2 replies; 17+ messages in thread
From: Victor Porton @ 2014-08-08 19:56 UTC (permalink / raw)


Shark8 wrote:

> On 08-Aug-14 10:56, Victor Porton wrote:
>>
>> But it is a hack.
> 
> How are you going to be able to tell which variant the subcomponent is
> though? The C union *doesn't* tag the varying part, so that information
> has to be kept elsewhere... or ignored completely.

For records interfacing with C it SHOULD be ignored completely. Because it 
is C.

>> I propose to change ARM not to require a discriminant in this specific
>> case (Unchecked_Union).
> 
> No.
> Just no.
> What you propose here would import from C weak typing -- if you want
> weak typing, why re you using Ada?

I want weak typing on request, to interface with C, but remaining in Ada.

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

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 19:52   ` Victor Porton
@ 2014-08-08 19:57     ` Adam Beneschan
  0 siblings, 0 replies; 17+ messages in thread
From: Adam Beneschan @ 2014-08-08 19:57 UTC (permalink / raw)


On Friday, August 8, 2014 12:52:41 PM UTC-7, Victor Porton wrote:
> Adam Beneschan wrote:

> OK, I followed your way, Adam.

No, you didn't.  Please reread my response carefully.

                                 -- Adam
 


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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 19:21 ` Per Sandberg
@ 2014-08-08 20:01   ` Victor Porton
  2014-08-08 21:23   ` Jeffrey Carter
  1 sibling, 0 replies; 17+ messages in thread
From: Victor Porton @ 2014-08-08 20:01 UTC (permalink / raw)


Per Sandberg wrote:

> You shall not try to write interface code by hand you shall use the
> compiler
> gcc -c -fdump-ada-spec <more arguments and files>
> see GNAT Users guide.
> 
> Since humans makes a heap load of errors and erronous asumptions when
> they try to translate the contents of a .h file to an .ads file, the
> compiler does a much better job.

I considered this approach but refused to use auto-generated code.

One reason is that it uses a system address type where it should be access 
arguments to a function. In my opinion, this is not guaranteed to work by 
ARM.

The other reason is that I can fine tune types. One especially useful usage 
pattern is that I sometimes pass char_array and sometimes chars_ptr to a 
function which requires a char or a void pointer. Also I can differentiate 
"access" arguments and pass-by-value, what is a sometimes useful 
distinction.

This use case simplifies my coding probably more that the necessity to write 
imported C functions manually.

And last it does not take really much time to code imported C functions 
manually. I may make errors here, but as for now I've instead found a few 
errors in the C library with which I am trying to interface.

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

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 19:56       ` Victor Porton
@ 2014-08-08 20:06         ` Pascal Obry
  2014-08-08 20:09         ` Shark8
  1 sibling, 0 replies; 17+ messages in thread
From: Pascal Obry @ 2014-08-08 20:06 UTC (permalink / raw)


Le vendredi 08 août 2014 à 22:56 +0300, Victor Porton a écrit : 
> For records interfacing with C it SHOULD be ignored completely. Because it 
> is C.

But again in Ada all must be explicit, this probably fall under this
rule. And what if you want to emulate the Ada tag on the C side and
actually have the tag exported? Not sure this is a real example as it
heavily depends on the compiler (and so the generated code).

-- 
  Pascal Obry /  Magny Les Hameaux (78)

  The best way to travel is by means of imagination

  http://v2p.fr.eu.org
  http://www.obry.net

  gpg --keyserver keys.gnupg.net --recv-key F949BD3B


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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 19:56       ` Victor Porton
  2014-08-08 20:06         ` Pascal Obry
@ 2014-08-08 20:09         ` Shark8
  2014-08-08 20:12           ` Victor Porton
  1 sibling, 1 reply; 17+ messages in thread
From: Shark8 @ 2014-08-08 20:09 UTC (permalink / raw)


On 08-Aug-14 13:56, Victor Porton wrote:
> For records interfacing with C it SHOULD be ignored completely. Because it
> is C.

Not in your example; the subcomponent is part of a record which is *not* 
a C-style union, it should therefore store the proper tag value 
(discriminant) in its own discriminant.

    type T2(K: Kind) is
       record
          Z: int;
          Ob: T(K);
       end record
    with Convention=>C;

Yields:
   warning: variant record has no direct equivalent in C
   warning: use of convention for type "T2" is dubious
So, remove Convention => C.


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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 20:09         ` Shark8
@ 2014-08-08 20:12           ` Victor Porton
  2014-08-08 20:22             ` Shark8
  0 siblings, 1 reply; 17+ messages in thread
From: Victor Porton @ 2014-08-08 20:12 UTC (permalink / raw)


Shark8 wrote:

> On 08-Aug-14 13:56, Victor Porton wrote:
>> For records interfacing with C it SHOULD be ignored completely. Because
>> it is C.
> 
> Not in your example; the subcomponent is part of a record which is *not*
> a C-style union, it should therefore store the proper tag value
> (discriminant) in its own discriminant.
> 
>     type T2(K: Kind) is
>        record
>           Z: int;
>           Ob: T(K);
>        end record
>     with Convention=>C;
> 
> Yields:
>    warning: variant record has no direct equivalent in C
>    warning: use of convention for type "T2" is dubious
> So, remove Convention => C.

You forgot "with Unchecked_Union". Certainly your code does not work.

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

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 20:12           ` Victor Porton
@ 2014-08-08 20:22             ` Shark8
  2014-08-08 20:28               ` Victor Porton
  0 siblings, 1 reply; 17+ messages in thread
From: Shark8 @ 2014-08-08 20:22 UTC (permalink / raw)


On 08-Aug-14 14:12, Victor Porton wrote:
> You forgot "with Unchecked_Union". Certainly your code does not work.

There's no unchecked union on T2, that was T in your example.

>
>    type T(K: Kind) is
>       record
>          case K is
>             when First  => I: int;
>             when Second => C: char;
>          end case;
>       end record
>    with Unchecked_Union, Convention=>C;
>
>    type T2 is
>       record
>          Z: int;
>          Ob: T;
>       end record
>    with Convention=>C;

See?

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 20:22             ` Shark8
@ 2014-08-08 20:28               ` Victor Porton
  2014-08-08 21:07                 ` Shark8
  0 siblings, 1 reply; 17+ messages in thread
From: Victor Porton @ 2014-08-08 20:28 UTC (permalink / raw)


Shark8 wrote:

> On 08-Aug-14 14:12, Victor Porton wrote:
>> You forgot "with Unchecked_Union". Certainly your code does not work.
> 
> There's no unchecked union on T2, that was T in your example.
> 
>>
>>    type T(K: Kind) is
>>       record
>>          case K is
>>             when First  => I: int;
>>             when Second => C: char;
>>          end case;
>>       end record
>>    with Unchecked_Union, Convention=>C;
>>
>>    type T2 is
>>       record
>>          Z: int;
>>          Ob: T;
>>       end record
>>    with Convention=>C;
> 
> See?

GNAT 4.9 produces no warnings for the below program.

Which compiler do you use? I suspect it is a bug in your compiler.

Or do we speak about different Ada code?

-- main.adb
with Interfaces.C; use Interfaces.C;

procedure Main is

   type Kind is (First, Second);

   type T(K: Kind := Kind'Last) is
      record
         case K is
            when First =>
               X: int;
            when Second =>
               Y: char;
         end case;
      end record
      with Unchecked_Union, Convention=>C;

   type Container is
      record
         Z: int;
         R: T;
      end record;

   function P (C: Container) return char is
   begin
      return C.R.Y;
   end;

begin
   null;
end;


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

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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 20:28               ` Victor Porton
@ 2014-08-08 21:07                 ` Shark8
  0 siblings, 0 replies; 17+ messages in thread
From: Shark8 @ 2014-08-08 21:07 UTC (permalink / raw)


On 08-Aug-14 14:28, Victor Porton wrote:
>
> Which compiler do you use? I suspect it is a bug in your compiler.

I'm using GNAT GPL 2013 (apparently 4.7.4)

> Or do we speak about different Ada code?

Well, given what you just posted, it looks like you renamed "T2" to 
"Container".


>    function P (C: Container) return char is
>    begin
>       return C.R.Y;
>    end;

Your Container type probably needs a tag.
Your function P should probably be something more like:

     function P (C: Container) return Character is
         Subtype Character_T is T(K => Second);
         Function Convert is new Unchecked_Conversion(
             Source => T,
             Target => Character_T
           );
     begin
         return Convert(C.R).Y; -- This ensures we get the character.
     end;


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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 19:21 ` Per Sandberg
  2014-08-08 20:01   ` Victor Porton
@ 2014-08-08 21:23   ` Jeffrey Carter
  2014-08-10  7:25     ` Per Sandberg
  1 sibling, 1 reply; 17+ messages in thread
From: Jeffrey Carter @ 2014-08-08 21:23 UTC (permalink / raw)


On 08/08/2014 12:21 PM, Per Sandberg wrote:
> You shall not try to write interface code by hand you shall use the compiler
>      gcc -c -fdump-ada-spec <more arguments and files>
> see GNAT Users guide.
>
> Since humans makes a heap load of errors and erronous asumptions when they try
> to translate the contents of a .h file to an .ads file, the compiler does a much
> better job.

While I agree with you in general, the results of -fdump-ada-spec need to be 
manually massaged since it produces non-portable, compiler-dependent code, such 
as using Address for C pointers. It may also be preferable to create a binding 
by hand if you only want a small subset of a large header.

-- 
Jeff Carter
"We call your door-opening request a silly thing."
Monty Python & the Holy Grail
17


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

* Re: Unchecked_Union record inside an other record - trouble
  2014-08-08 21:23   ` Jeffrey Carter
@ 2014-08-10  7:25     ` Per Sandberg
  0 siblings, 0 replies; 17+ messages in thread
From: Per Sandberg @ 2014-08-10  7:25 UTC (permalink / raw)


Yes of couse -fdump-ada-spec is for GCC-gnat but even if you want to 
take a small subset I find it more efficent and much less errorprone to 
start with the generated spec:s and edit the generated code  afterwards.

(have done this with a fairtly large API:

550 header-files
7500 methods
5500 types

and some small ones as well.

/per

On 08.08.2014 23:23, Jeffrey Carter wrote:
> On 08/08/2014 12:21 PM, Per Sandberg wrote:
>> You shall not try to write interface code by hand you shall use the
>> compiler
>>      gcc -c -fdump-ada-spec <more arguments and files>
>> see GNAT Users guide.
>>
>> Since humans makes a heap load of errors and erronous asumptions when
>> they try
>> to translate the contents of a .h file to an .ads file, the compiler
>> does a much
>> better job.
>
> While I agree with you in general, the results of -fdump-ada-spec need
> to be manually massaged since it produces non-portable,
> compiler-dependent code, such as using Address for C pointers. It may
> also be preferable to create a binding by hand if you only want a small
> subset of a large header.
>


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

end of thread, other threads:[~2014-08-10  7:25 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-08 15:36 Unchecked_Union record inside an other record - trouble Victor Porton
2014-08-08 16:01 ` Adam Beneschan
2014-08-08 16:56   ` Victor Porton
2014-08-08 18:52     ` Shark8
2014-08-08 19:56       ` Victor Porton
2014-08-08 20:06         ` Pascal Obry
2014-08-08 20:09         ` Shark8
2014-08-08 20:12           ` Victor Porton
2014-08-08 20:22             ` Shark8
2014-08-08 20:28               ` Victor Porton
2014-08-08 21:07                 ` Shark8
2014-08-08 19:52   ` Victor Porton
2014-08-08 19:57     ` Adam Beneschan
2014-08-08 19:21 ` Per Sandberg
2014-08-08 20:01   ` Victor Porton
2014-08-08 21:23   ` Jeffrey Carter
2014-08-10  7:25     ` Per Sandberg

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