comp.lang.ada
 help / color / mirror / Atom feed
* generic package with procedure paramter gives "not subtype conformant with declaration"
@ 2006-09-30 21:20 cl1
  2006-10-01  1:27 ` Jeffrey R. Carter
  2006-10-01  7:18 ` Simon Wright
  0 siblings, 2 replies; 16+ messages in thread
From: cl1 @ 2006-09-30 21:20 UTC (permalink / raw)


I don't understand why i can't pass Av_Param to the generic package (in
test_call_avcall_register_type.adb) and have its 'Access attribute used
in Concat (the offending code in avcall-register_type.adb)?

i'm getting the following error:
$ gnatmake -gnatc ./Ada_Source/test_avcall_register_type.adb
gcc -c -I./Ada_Source/ -gnatc -I-
./Ada_Source/test_avcall_register_type.adb
gcc -c -I./Ada_Source/ -gnatc -I- ./Ada_Source/avcall.adb
gcc -c -I./Ada_Source/ -gnatc -I- ./Ada_Source/avcall-register_type.adb
avcall-register_type.adb:13:34: not subtype conformant with declaration
at avcall.ads:37
avcall-register_type.adb:13:34: formal subprograms not allowed
gnatmake: "./Ada_Source/avcall-register_type.adb" compilation error

on this code:
<avcall.ads>
with System; use System;
package avcall is
	-- <snip>
	----------------------------------------------------------------------------
	-- This exeption is thrown when you try to add more than Max_Args to
the
	-- Var_Args type
	Max_Arg_Limit_Surpassed : exception;
	----------------------------------------------------------------------------
	-- The maximum number of arguments that can be used by avcall
	Max_Args : constant := 50;
	----------------------------------------------------------------------------
	-- this is the number of arguments in the Var_Args list
	subtype Arg_Count is Natural range 0..Max_Args;
	----------------------------------------------------------------------------
	-- This is the range used by the Var_Args list
	subtype Arg_Range is Natural range 1..Max_Args;
	----------------------------------------------------------------------------
	-- this represents an argument held in the Arg_List
	type Argument is tagged
		record
		------------------------------------------------------------------------
		-- This holds the correct av_<type> c function to call.
		Av_Param : access procedure(Av_List : System.Address;
									Value : System.Address);
		------------------------------------------------------------------------
		-- This holds the address of the value. This is assigned by the child
		-- type of this type in the Register_Type package during the
		-- Initialize procedure call of the child type.
		Value_Address : System.Address;
		------------------------------------------------------------------------
		end record;
	----------------------------------------------------------------------------
	-- This type is used by the Var_Args type to hold all of the
arguments.
	type Arg_List is array(Arg_Range range <>) of Argument;
	----------------------------------------------------------------------------
	-- This is the Var_Args type. This is used to hold all of the
arguments to
	-- the c function (the ... and all the arguments before that).
	-- The Start_Var_Args, "&", and Prepend methods and functions are used
to
	-- add arguments to Var_Args.
	type Var_Args is
		record
		------------------------------------------------------------------------
		-- this is a pointer to the c data type that makes this work.
		-- Av_List_Malloc and Av_List_Free (defined in the body) are used to
		-- obtain the reference and free it respectivly
		Av_List : System.Address;
		------------------------------------------------------------------------
		-- This is the number of arguments in the Arg_List
		Count : access Arg_Count;
		------------------------------------------------------------------------
		-- This is what holds all of the arguments.
		List : access Arg_List := new Arg_List(Arg_Range'Range);
		------------------------------------------------------------------------
		end record;
	----------------------------------------------------------------------------
	-- <snip>
end avcall;

<avcall-register_type.ads>
with System.Address_To_Access_Conversions;
with System; use System;
--------------------------------------------------------------------------------
generic
	type Any_Type is private;
	with procedure Av_Param_Instance(AList : System.Address; Value :
System.Address);
package avcall.register_type is
	----------------------------------------------------------------------------
	package Any_Type_Conversion is new
System.Address_To_Access_Conversions(Any_Type);
	----------------------------------------------------------------------------
	type Argument_Instance is new Argument with
		record
			Instance_Value : Any_Type_Conversion.Object_Pointer;
		end record;
	----------------------------------------------------------------------------
	function Concat(AList : Var_Args; Arg : Any_Type) return Var_Args;
	----------------------------------------------------------------------------
end avcall.register_type;

<avcall-register_type.adb>
package body avcall.register_type is
	----------------------------------------------------------------------------
	-- Adds the value in Arg to the next Var_Args.List
	function Concat(AList : Var_Args; Arg : Any_Type) return Var_Args is
		Info : Argument_Instance;
	begin
		Info.Av_Param := Av_Param_Instance'Access;
		Info.Instance_Value.all := Arg;
		Info.Value_Address :=
Any_Type_Conversion.To_Address(Info.Instance_Value);
		AList.Count.all := AList.Count.all + 1;
		AList.List(AList.Count.all) := Argument(Info);
		return AList;
	end Concat;
	----------------------------------------------------------------------------
end avcall.register_type;

<test_avcall_register_type.adb>
with avcall; use avcall;
with avcall.register_type;
with Ada.Text_IO; use Ada.Text_IO;
with System; use System;
--------------------------------------------------------------------------------
procedure test_avcall_register_type is
	procedure Av_Param(AList : System.Address; Value : System.Address) is
	begin
		null;
	end Av_Param;
	package Int_Registered is new avcall.register_type(Integer, Av_Param);
begin
	Put_Line("FOO");
end test_avcall_register_type;

<offending code>
--avcall-register_type.adb:13:34: not subtype conformant with
declaration at avcall.ads:37
--avcall-register_type.adb:13:34: formal subprograms not allowed
		Info.Av_Param := Av_Param_Instance'Access;
<end of code post>

I don't understand why i can't pass Av_Param to the generic package (in
test_call_avcall_register_type.adb) and have its 'Access attribute used
in Concat (the offending code in avcall-register_type.adb)?




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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-09-30 21:20 generic package with procedure paramter gives "not subtype conformant with declaration" cl1
@ 2006-10-01  1:27 ` Jeffrey R. Carter
  2006-10-01  6:02   ` cl1
  2006-10-01  7:18 ` Simon Wright
  1 sibling, 1 reply; 16+ messages in thread
From: Jeffrey R. Carter @ 2006-10-01  1:27 UTC (permalink / raw)


cl1 wrote:
> --avcall-register_type.adb:13:34: not subtype conformant with
> declaration at avcall.ads:37
> --avcall-register_type.adb:13:34: formal subprograms not allowed
> 		Info.Av_Param := Av_Param_Instance'Access;
> <end of code post>

You seem to have cut things down a bit too much. avcall.ads has no line 
37. If you're going to cut things down this much, please post messages 
that result from compiling the cut-down code.

You shouldn't use System.Address to interface to C. Use a convention-C 
access type instead.

> I don't understand why i can't pass Av_Param to the generic package (in
> test_call_avcall_register_type.adb) and have its 'Access attribute used
> in Concat (the offending code in avcall-register_type.adb)?

You don't say what version of GNAT you're using. However, I suspect what 
you're running into is an accessibility control problem. You can't store 
the generic formal procedure's 'access because the compiler can't be 
sure that the life of the access value is no longer than the life of the 
actual procedure.

-- 
Jeff Carter
"Sir Lancelot saves Sir Gallahad from almost certain temptation."
Monty Python & the Holy Grail
69



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01  1:27 ` Jeffrey R. Carter
@ 2006-10-01  6:02   ` cl1
  2006-10-01 19:43     ` Jeffrey R. Carter
  0 siblings, 1 reply; 16+ messages in thread
From: cl1 @ 2006-10-01  6:02 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> cl1 wrote:
> > --avcall-register_type.adb:13:34: not subtype conformant with
> > declaration at avcall.ads:37
> > --avcall-register_type.adb:13:34: formal subprograms not allowed
> > 		Info.Av_Param := Av_Param_Instance'Access;
> > <end of code post>
>
> You seem to have cut things down a bit too much. avcall.ads has no line
> 37. If you're going to cut things down this much, please post messages
> that result from compiling the cut-down code.

that is why i posted the very last section called <offending code> so
you could see which line it was. I didn't think to compile the cut down
code.
I appologize. line 37 is lines 23 and 24 in the snippet of avcall.ads

>
> You shouldn't use System.Address to interface to C. Use a convention-C
> access type instead.

I understand the reason for using access types with convention C, but
that
will not work for this situation. Everywhere i have used System.Address
the code
does not know, does not care what type or subprogram signature is
stored there, and will
not use it other than to pass it along to some c function that knows
what to do with it. If
there is a System.Address being used that doesn't fit that, then it is
a bug. I also choose
not to use 'type void_ptr is new System.Address;' specifically becuase
that is what
System.Address is. Also someone once told me that writing code that
requires the user
to with System; alerts the user that the code is system dependant. I
like that idea. This
code is system dependant. By that, I mean it is dependant on the
processor and in
some situations the operating system, not the compiler implementation.
Well to be
honest the Ada code isn't but the C code it interfaces with is
(ffcall's avcall).

>
> > I don't understand why i can't pass Av_Param to the generic package (in
> > test_call_avcall_register_type.adb) and have its 'Access attribute used
> > in Concat (the offending code in avcall-register_type.adb)?
>
> You don't say what version of GNAT you're using.

i'm using GPS which has gcc version 3.4.6 on mac os x 10.4.8

> However, I suspect what
> you're running into is an accessibility control problem. You can't store
> the generic formal procedure's 'access because the compiler can't be
> sure that the life of the access value is no longer than the life of the
> actual procedure.

I agree with you.
However, I am confused about this. The procedure could be declared
anywhere. How
does the compiler know what scope the procedure that is supplied to the
generic package is in? I mean can it ever know? If not, that means
there
is no foreseeable fix to this issue from my point of view.
>
> --
> Jeff Carter
> "Sir Lancelot saves Sir Gallahad from almost certain temptation."
> Monty Python & the Holy Grail
> 69




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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-09-30 21:20 generic package with procedure paramter gives "not subtype conformant with declaration" cl1
  2006-10-01  1:27 ` Jeffrey R. Carter
@ 2006-10-01  7:18 ` Simon Wright
  2006-10-01 19:42   ` cl1
  1 sibling, 1 reply; 16+ messages in thread
From: Simon Wright @ 2006-10-01  7:18 UTC (permalink / raw)


Put this somewhere (in package avcall I guess)

   type Av_Param_Access
     is access procedure (AList : System.Address;
                          Value : System.Address);

then 

   generic
      type Any_Type is private;
      Av_Param_Instance : Av_Param_Access;
   package avcall.register_type is

Compiles OK (same environment as you), whether it is correct and
whether it works are of course different matters.



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01  7:18 ` Simon Wright
@ 2006-10-01 19:42   ` cl1
  2006-10-01 20:18     ` Robert A Duff
  0 siblings, 1 reply; 16+ messages in thread
From: cl1 @ 2006-10-01 19:42 UTC (permalink / raw)


Simon Wright wrote:
> Put this somewhere (in package avcall I guess)
>
>    type Av_Param_Access
>      is access procedure (AList : System.Address;
>                           Value : System.Address);
>
> then
>
>    generic
>       type Any_Type is private;
>       Av_Param_Instance : Av_Param_Access;
>    package avcall.register_type is
>
> Compiles OK (same environment as you), whether it is correct and
> whether it works are of course different matters.

Thank you very much.
It fixed the problem, but i do not understand why:
with procedure Av_Param_Instance(Av_List, Value : System.Address);
does not work. If anyone knows why, I would be greatfull for an
explination.




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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01  6:02   ` cl1
@ 2006-10-01 19:43     ` Jeffrey R. Carter
  2006-10-01 21:26       ` cl1
  0 siblings, 1 reply; 16+ messages in thread
From: Jeffrey R. Carter @ 2006-10-01 19:43 UTC (permalink / raw)


cl1 wrote:
> 
> I understand the reason for using access types with convention C, but
> that
> will not work for this situation. Everywhere i have used System.Address
> the code
> does not know, does not care what type or subprogram signature is
> stored there, and will
> not use it other than to pass it along to some c function that knows
> what to do with it. If
> there is a System.Address being used that doesn't fit that, then it is
> a bug. I also choose
> not to use 'type void_ptr is new System.Address;' specifically becuase
> that is what
> System.Address is. Also someone once told me that writing code that
> requires the user
> to with System; alerts the user that the code is system dependant. I
> like that idea. This
> code is system dependant. By that, I mean it is dependant on the
> processor and in
> some situations the operating system, not the compiler implementation.
> Well to be
> honest the Ada code isn't but the C code it interfaces with is
> (ffcall's avcall).

The problem is that System.Address is not guaranteed to be the same as a 
C pointer, so using it to interface with C makes your code compiler 
dependent. In all versions of GNAT that I've used and bothered to check, 
System.Address has been the same as a C pointer, but that could change 
at any time.

For types, any convention-C access type will work for a void pointer 
when the values come from C and are never dereferenced by the Ada. I 
generally use "access all Integer" for that case, though some people 
prefer to have a void type to designate:

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

Since values of Void_Ptr are never dereferenced, the designated type 
doesn't matter.

For subprograms, it's more complicated because you have to match the 
subprogram parameter and return type profile. In your case, though 
(IIRC), the subprograms all have the same profile (that of your generic 
formal subprogram), so the use of a convention-C access type seems to be 
possible.

> i'm using GPS which has gcc version 3.4.6 on mac os x 10.4.8

GPS is an IDE, not a compiler, but gcc 3.4.6 is; it's an Ada-95 
compiler. The compiler version is of interest because Ada 95's 
accessibility rules differ from Ada 0X's.

> I agree with you.
> However, I am confused about this. The procedure could be declared
> anywhere. How
> does the compiler know what scope the procedure that is supplied to the
> generic package is in? I mean can it ever know? If not, that means
> there
> is no foreseeable fix to this issue from my point of view.

The compiler can't know the scope of the actual procedure in general; 
that's why you can never store the 'access of a generic formal 
procedure. The language assumes the worst case for safety.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail
09



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01 19:42   ` cl1
@ 2006-10-01 20:18     ` Robert A Duff
  2006-10-01 21:32       ` cl1
  0 siblings, 1 reply; 16+ messages in thread
From: Robert A Duff @ 2006-10-01 20:18 UTC (permalink / raw)


"cl1" <charles.w.lambert@gmail.com> writes:

> Thank you very much.
> It fixed the problem, but i do not understand why:
> with procedure Av_Param_Instance(Av_List, Value : System.Address);
> does not work. If anyone knows why, I would be greatfull for an
> explination.

And you wanted to do Av_Param_Instance'Access inside the generic?

That won't work, because the compiler can't check the rules about
X'Access, because it doesn't know enough about the actual parameter
passed to Av_Param_Instance.  The accessibility rules come to mind.
Also, the fact that you can't do X'Access if X is intrinsic.

- Bob



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01 19:43     ` Jeffrey R. Carter
@ 2006-10-01 21:26       ` cl1
  2006-10-01 23:17         ` tmoran
  2006-10-02  3:24         ` Jeffrey R. Carter
  0 siblings, 2 replies; 16+ messages in thread
From: cl1 @ 2006-10-01 21:26 UTC (permalink / raw)



Jeffrey R. Carter wrote:
> cl1 wrote:
> > <snip>
>
> The problem is that System.Address is not guaranteed to be the same as a
> C pointer, so using it to interface with C makes your code compiler
> dependent. In all versions of GNAT that I've used and bothered to check,
> System.Address has been the same as a C pointer, but that could change
> at any time.

I did not know this. I am forever learning, it seems.

>
> For types, any convention-C access type will work for a void pointer
> when the values come from C and are never dereferenced by the Ada. I
> generally use "access all Integer" for that case, though some people
> prefer to have a void type to designate:
>
> type Void is null record;
> type Void_Ptr is access all Void;
> pragma Convention (C, Void_Ptr);

This is a very good concept. Is there a mechanism in ada to allow:

My_Void_Ptr := My_C_Float'Access;

where My_C_Float could be My_New_Type or My_Integer, etc.
I ask, because my code does this and i was using the System.Address as
a catch all. Once i store the access in the pointer i no longer need to
know
what type it is. I just need the reference to pass to the C code. For
instance:

package avcall is
type Argument is
  record
    Value_Address : System.Address;
  end record;
end avcall;

generic
  type Any_Type is private;
package avcall.register_type
  package Any_Type_Conversion is new
System.Address_To_Access_Conversions(Any_Type);
  type Argument_Instance is
    record
      Instance_Value : Any_Type_Conversion.Object_Pointer;
    end record;
    function Concat(AList : Var_Args; Arg : Any_Type) return Var_Args
is
      Info : Argument_Instance;
    begin
      Info.Instance_Value := Arg;
      Info.Value_Address :=
Any_Type_Conversion.To_Address(Info.Instance_Value);
      return AList;
    end;
end avcall.register_type;

This is how i'm currently doing things. How would i change my
Argument.Value_Address from System.Address type to something like the
Void_Ptr type you proposed? So that i can change:

Info.Value_Address :=
Any_Type_Conversion.To_Address(Info.Instance_Value);

to work with the Void_Ptr type.


>
> Since values of Void_Ptr are never dereferenced, the designated type
> doesn't matter.
>
> For subprograms, it's more complicated because you have to match the
> subprogram parameter and return type profile. In your case, though
> (IIRC), the subprograms all have the same profile (that of your generic
> formal subprogram), so the use of a convention-C access type seems to be
> possible.
>
> > i'm using GPS which has gcc version 3.4.6 on mac os x 10.4.8
>
> GPS is an IDE, not a compiler, but gcc 3.4.6 is; it's an Ada-95
> compiler. The compiler version is of interest because Ada 95's
> accessibility rules differ from Ada 0X's.
>
> > I agree with you.
> > However, I am confused about this. The procedure could be declared
> > anywhere. How
> > does the compiler know what scope the procedure that is supplied to the
> > generic package is in? I mean can it ever know? If not, that means
> > there
> > is no foreseeable fix to this issue from my point of view.
>
> The compiler can't know the scope of the actual procedure in general;
> that's why you can never store the 'access of a generic formal
> procedure. The language assumes the worst case for safety.

to quote another post in this thread:

-And you wanted to do Av_Param_Instance'Access inside the generic?
-That won't work, because the compiler can't check the rules about
-X'Access, because it doesn't know enough about the actual parameter
-passed to Av_Param_Instance.  The accessibility rules come to mind.
-Also, the fact that you can't do X'Access if X is intrinsic

Now that i know that is the rule. I not only understand what was
causing
the problem, but why.

>
> --
> Jeff Carter
> "Monsieur Arthur King, who has the brain of a duck, you know."
> Monty Python & the Holy Grail
> 09




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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01 20:18     ` Robert A Duff
@ 2006-10-01 21:32       ` cl1
  0 siblings, 0 replies; 16+ messages in thread
From: cl1 @ 2006-10-01 21:32 UTC (permalink / raw)



Robert A Duff wrote:
> "cl1" <charles.w.lambert@gmail.com> writes:
>
> > Thank you very much.
> > It fixed the problem, but i do not understand why:
> > with procedure Av_Param_Instance(Av_List, Value : System.Address);
> > does not work. If anyone knows why, I would be greatfull for an
> > explination.
>
> And you wanted to do Av_Param_Instance'Access inside the generic?
>
> That won't work, because the compiler can't check the rules about
> X'Access, because it doesn't know enough about the actual parameter
> passed to Av_Param_Instance.  The accessibility rules come to mind.
> Also, the fact that you can't do X'Access if X is intrinsic.

Now that I know that is the rule, everything is clear once again. I had
made the assumption that it would work based on the definition in the
arm on how generic packages are elaborated. I love how Ada is so well
defined. Now if i could just memorize the ARM ... :-D


> 
> - Bob




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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01 21:26       ` cl1
@ 2006-10-01 23:17         ` tmoran
  2006-10-02  4:46           ` cl1
  2006-10-02  3:24         ` Jeffrey R. Carter
  1 sibling, 1 reply; 16+ messages in thread
From: tmoran @ 2006-10-01 23:17 UTC (permalink / raw)


> > For types, any convention-C access type will work for a void pointer
> > when the values come from C and are never dereferenced by the Ada.
> ...
> Once i store the access in the pointer i no longer need to know
> what type it is. I just need the reference to pass to the C code.
   Maybe I'm not understanding but if the values come from C and are
never used by Ada, but merely passed on to other calls on C, why not
just declare them as
  type C_Param is new Interfaces.Unsigned_32;
and treat them in Ada as a black box, size 32, content unknown.



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01 21:26       ` cl1
  2006-10-01 23:17         ` tmoran
@ 2006-10-02  3:24         ` Jeffrey R. Carter
  2006-10-02  4:31           ` cl1
  1 sibling, 1 reply; 16+ messages in thread
From: Jeffrey R. Carter @ 2006-10-02  3:24 UTC (permalink / raw)


cl1 wrote:
> 
> This is a very good concept. Is there a mechanism in ada to allow:
> 
> My_Void_Ptr := My_C_Float'Access;
> 
> where My_C_Float could be My_New_Type or My_Integer, etc.
> I ask, because my code does this and i was using the System.Address as
> a catch all. Once i store the access in the pointer i no longer need to
> know
> what type it is. I just need the reference to pass to the C code. For
> instance:

If the access values come from Ada, it gets a bit more complicated. 
However, C pointers are convertible from one type to another, IIRC, so 
that works for you. You need to declare a convention-C access type for 
the type you use, store the 'access in one of those, then unchecked 
convert that value to the void pointer type. A generic can make that easier:

with Ada.Unchecked_Conversion;
...
type Void_Ptr is ...
...
generic -- Void_Conversion
    type T (<>) is limited private;
package Void_Conversion is
    type T_Ptr is access all T;
    pragma Convention (C, T_Ptr);

    function To_Void_Ptr is new Ada.Unchecked_Conversion
    (Source => T_Ptr, Target => Void_Ptr);
end Void_Conversion;

Then you can do

package C_Float_Convert is new Void_Conversions (T => C_Float);

T_Ptr : constant C_Float_Convert.T_Ptr := My_C_Float'access;

My_Void_Ptr : Void_Ptr := C_Float_Convert.To_Void_Ptr (T_Ptr);

> Now that i know that is the rule. I not only understand what was
> causing
> the problem, but why.

That's usually a good thing.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail
09



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-02  3:24         ` Jeffrey R. Carter
@ 2006-10-02  4:31           ` cl1
  2006-10-02  7:17             ` Alex R. Mosteo
  2006-10-02 20:04             ` Jeffrey R. Carter
  0 siblings, 2 replies; 16+ messages in thread
From: cl1 @ 2006-10-02  4:31 UTC (permalink / raw)



Jeffrey R. Carter wrote:
> cl1 wrote:
> >
> > This is a very good concept. Is there a mechanism in ada to allow:
> >
> > My_Void_Ptr := My_C_Float'Access;
> >
> > where My_C_Float could be My_New_Type or My_Integer, etc.
> > I ask, because my code does this and i was using the System.Address as
> > a catch all. Once i store the access in the pointer i no longer need to
> > know
> > what type it is. I just need the reference to pass to the C code. For
> > instance:
>
> If the access values come from Ada, it gets a bit more complicated.
> However, C pointers are convertible from one type to another, IIRC, so
> that works for you. You need to declare a convention-C access type for
> the type you use, store the 'access in one of those, then unchecked
> convert that value to the void pointer type. A generic can make that easier:
>
> with Ada.Unchecked_Conversion;
> ...
> type Void_Ptr is ...
> ...
> generic -- Void_Conversion
>     type T (<>) is limited private;
> package Void_Conversion is
>     type T_Ptr is access all T;
>     pragma Convention (C, T_Ptr);
>
>     function To_Void_Ptr is new Ada.Unchecked_Conversion
>     (Source => T_Ptr, Target => Void_Ptr);
> end Void_Conversion;

Genius, pure genius! :D

Thank you.

so now my System.Address becomes Void_Access via:

with Ada.Unchecked_Conversion;
package General_Conversion
   type Void is null record;
   type Void_Access is access all Void;
   pragma Convention(C, Void_Access);

   generic
      type Any_C_Convention_Type (<>) is limited private;
   package Void_Conversion is
      type Convert_From_Access is access all Any_C_Convention_Type;
      pragma Convetion(C, Convert_From_Access);

      function To_Void_Access is new Ada.Unchecked_Conversion(
        Source => Convert_From_Access;
            Target => Void_Access);
end General_Conversion;


A bit more wordy. But at least it is correct.

For anyone who is curious. This crazy code is being implemented so that
you can call variable argument c functions. It interfaces with ffcall's
avcall which is like, as they describe, av_list in reverse. So far I
have the code that autogenerates wrappers for the avcall macros. The
code I orginally posted is the code to store all the parameters to the
variable argument C function. The process for a user of my packages
should be:
1. write a bit of code (8 lines for 1 type, and 1 additional line for
each new type) to autogenerate ada and c functions/procedures to
interface with ffcall for your types( The Interfaces.C types already
have wrappers)
2. Create a wrapper function for the variable argument C function you
want to call. This example is missing the recently disscussed Void_Ptr
type:
package body Example is
	-- here is your variable argument function
	procedure My_Var_Args(Item1 : Int; Args : Var_Args) is
		-- here is the real variable argument c function
		procedure c_my_var_args;
		pragma Import(C, c_my_var_args, "my_var_args");
		-- here is your return value from your c_my_var_args function
		Return_Value : Int;
		-- set Av_Start to the generated av_start wrapper function
		-- autogenerated with the functions in ffcall.avcallextensions
package
		Av_Start : Av_Start_Access := av_start_foo_ptr;
	begin
		-- add your defined argments to the front of Var_Args
		Prepend(Args, Item1);
		-- call your function(c_my_var_args)
		Call(Args, c_my_var_args'Address, Return_Value'Address,
av_start_Foo_ptr'Access);
		-- return your return value
		return Return_Value;
	end My_Var_Args;
end Example;

3. Then use the new function or procedure like so:
My_Var_Args(a, b, Start_Var_Args & p1 & p2 & p3 & pN);

The only limitation is that you can pass struct pointers but not
structs themselves as parameters. ffcall however has macros for passing
structs, so if that were imperative, you could manually make a c
function wrapper for those macros and an ada corespondance. which could
be used with the rest of my system.

I plan on redesigning/reimplementing all instances of System.Address to
this new Void_Ptr scheme.

Just thought you might like to know what you have been helping with
Thanks again.



>
> Then you can do
>
> package C_Float_Convert is new Void_Conversions (T => C_Float);
>
> T_Ptr : constant C_Float_Convert.T_Ptr := My_C_Float'access;
>
> My_Void_Ptr : Void_Ptr := C_Float_Convert.To_Void_Ptr (T_Ptr);
>
> > Now that i know that is the rule. I not only understand what was
> > causing
> > the problem, but why.
>
> That's usually a good thing.
>
> --
> Jeff Carter
> "Monsieur Arthur King, who has the brain of a duck, you know."
> Monty Python & the Holy Grail
> 09




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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-01 23:17         ` tmoran
@ 2006-10-02  4:46           ` cl1
  0 siblings, 0 replies; 16+ messages in thread
From: cl1 @ 2006-10-02  4:46 UTC (permalink / raw)



tmoran@acm.org wrote:
> > > For types, any convention-C access type will work for a void pointer
> > > when the values come from C and are never dereferenced by the Ada.
> > ...
> > Once i store the access in the pointer i no longer need to know
> > what type it is. I just need the reference to pass to the C code.
>    Maybe I'm not understanding but if the values come from C and are
> never used by Ada, but merely passed on to other calls on C, why not
> just declare them as
>   type C_Param is new Interfaces.Unsigned_32;
> and treat them in Ada as a black box, size 32, content unknown.

The values come from ada.




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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-02  4:31           ` cl1
@ 2006-10-02  7:17             ` Alex R. Mosteo
  2006-10-02 20:04             ` Jeffrey R. Carter
  1 sibling, 0 replies; 16+ messages in thread
From: Alex R. Mosteo @ 2006-10-02  7:17 UTC (permalink / raw)


cl1 wrote:

> 
> Jeffrey R. Carter wrote:
>> cl1 wrote:
>> >
>> > This is a very good concept. Is there a mechanism in ada to allow:
>> >
>> > My_Void_Ptr := My_C_Float'Access;
>> >
>> > where My_C_Float could be My_New_Type or My_Integer, etc.
>> > I ask, because my code does this and i was using the System.Address as
>> > a catch all. Once i store the access in the pointer i no longer need to
>> > know
>> > what type it is. I just need the reference to pass to the C code. For
>> > instance:
>>
>> If the access values come from Ada, it gets a bit more complicated.
>> However, C pointers are convertible from one type to another, IIRC, so
>> that works for you. You need to declare a convention-C access type for
>> the type you use, store the 'access in one of those, then unchecked
>> convert that value to the void pointer type. A generic can make that
>> easier:
>>
>> with Ada.Unchecked_Conversion;
>> ...
>> type Void_Ptr is ...
>> ...
>> generic -- Void_Conversion
>>     type T (<>) is limited private;
>> package Void_Conversion is
>>     type T_Ptr is access all T;
>>     pragma Convention (C, T_Ptr);
>>
>>     function To_Void_Ptr is new Ada.Unchecked_Conversion
>>     (Source => T_Ptr, Target => Void_Ptr);
>> end Void_Conversion;
> 
> Genius, pure genius! :D
> 
> Thank you.

You can see an example of a binding using this technique in 

http://sourceforge.net/projects/ada-player

Therein are types coming from the C and Ada side being used in calls to the
C side.

It is an Ada-C binding for the robotic controller Player:

http://playerstage.sf.net



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-02  4:31           ` cl1
  2006-10-02  7:17             ` Alex R. Mosteo
@ 2006-10-02 20:04             ` Jeffrey R. Carter
  2006-10-03 18:49               ` cl1
  1 sibling, 1 reply; 16+ messages in thread
From: Jeffrey R. Carter @ 2006-10-02 20:04 UTC (permalink / raw)


cl1 wrote:
> 
> Genius, pure genius! :D

Thanks. More accurately, experience and a desire to be portable whenever 
possible.

> For anyone who is curious. This crazy code is being implemented so that
> you can call variable argument c functions. It interfaces with ffcall's
> avcall which is like, as they describe, av_list in reverse. So far I
> have the code that autogenerates wrappers for the avcall macros. The
> code I orginally posted is the code to store all the parameters to the
> variable argument C function. The process for a user of my packages
> should be:

I guess you have to handle any number of arguments. For specific or 
commonly used cases, you can declare multiple Ada subprograms, each with 
different numbers or types of parameters, that all pragma Import the 
same C function. Since you're generating packages for your clients, 
perhaps it would be easier on your clients if you generated such 
specific subprograms for them.

For example:

package C renames Interfaces.C;

procedure Print_Str (Format : in C.Char_Array; Str : in C.Char_Array);
pragma Import (C, Print_Str, "printf");

procedure Print_Int (Format : in C.Char_Array; Num : in C.Int);
pragma Import (C, Print_Int, "printf");

procedure Print_Str_Int (Format : in C.Char_Array;
                          Str    : in C.Char_Array;
                          Num    : in C.Int);
pragma Import (C, Print_Str_Int, "printf");

-- 
Jeff Carter
"It's all right, Taggart. Just a man and a horse being hung out there."
Blazing Saddles
34



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

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  2006-10-02 20:04             ` Jeffrey R. Carter
@ 2006-10-03 18:49               ` cl1
  0 siblings, 0 replies; 16+ messages in thread
From: cl1 @ 2006-10-03 18:49 UTC (permalink / raw)



Jeffrey R. Carter wrote:
> cl1 wrote:
> >
> > Genius, pure genius! :D
>
> Thanks. More accurately, experience and a desire to be portable whenever
> possible.
>
> > For anyone who is curious. This crazy code is being implemented so that
> > you can call variable argument c functions. It interfaces with ffcall's
> > avcall which is like, as they describe, av_list in reverse. So far I
> > have the code that autogenerates wrappers for the avcall macros. The
> > code I orginally posted is the code to store all the parameters to the
> > variable argument C function. The process for a user of my packages
> > should be:
>
> I guess you have to handle any number of arguments. For specific or
> commonly used cases, you can declare multiple Ada subprograms, each with
> different numbers or types of parameters, that all pragma Import the
> same C function. Since you're generating packages for your clients,
> perhaps it would be easier on your clients if you generated such
> specific subprograms for them.
>
> For example:
>
> package C renames Interfaces.C;
>
> procedure Print_Str (Format : in C.Char_Array; Str : in C.Char_Array);
> pragma Import (C, Print_Str, "printf");
>
> procedure Print_Int (Format : in C.Char_Array; Num : in C.Int);
> pragma Import (C, Print_Int, "printf");
>
> procedure Print_Str_Int (Format : in C.Char_Array;
>                           Str    : in C.Char_Array;
>                           Num    : in C.Int);
> pragma Import (C, Print_Str_Int, "printf");
>
> --
> Jeff Carter
> "It's all right, Taggart. Just a man and a horse being hung out there."
> Blazing Saddles
> 34

If my information serves me correctly, Ada doesn't define what happens
when you import variable argument functions like that. It recomends
that the only sure way is to write a c function wrapper that calls the
variable argument function.

The cool thing about ffcall's avcall is that I only have to write 2
wrapper functions for each type. One for the case where it is a return
value, and one where it is an argument to the function. That is what my
autogeneration code does. It writes those wrapper functions, and the
coresponding ada procedures and their pramga import.




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

end of thread, other threads:[~2006-10-03 18:49 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-09-30 21:20 generic package with procedure paramter gives "not subtype conformant with declaration" cl1
2006-10-01  1:27 ` Jeffrey R. Carter
2006-10-01  6:02   ` cl1
2006-10-01 19:43     ` Jeffrey R. Carter
2006-10-01 21:26       ` cl1
2006-10-01 23:17         ` tmoran
2006-10-02  4:46           ` cl1
2006-10-02  3:24         ` Jeffrey R. Carter
2006-10-02  4:31           ` cl1
2006-10-02  7:17             ` Alex R. Mosteo
2006-10-02 20:04             ` Jeffrey R. Carter
2006-10-03 18:49               ` cl1
2006-10-01  7:18 ` Simon Wright
2006-10-01 19:42   ` cl1
2006-10-01 20:18     ` Robert A Duff
2006-10-01 21:32       ` cl1

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