comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Calling Ada Procedure from C - how to handle a char ptr/array
Date: Fri, 18 Nov 2011 18:16:55 -0800 (PST)
Date: 2011-11-18T18:16:55-08:00	[thread overview]
Message-ID: <a05c4971-737f-447b-b271-b161ad7d702c@y15g2000prl.googlegroups.com> (raw)
In-Reply-To: 8e5541a3-cdd5-40af-a6fd-f7539ee61326@l19g2000yqc.googlegroups.com

On Nov 18, 11:40 am, awdorrin <awdor...@gmail.com> wrote:
> What would be the recommended way to pass a C char pointer or char
> array into an Ada function or procedure that will be called from a C
> program?
>
> After reading through the Interfaces.C.* packages, I'm assuming I
> could do something like this:
>
> In my Ada procedure:
>
> procedure Get_Text( s : out Interfaces.C.char_array) is
>   Label : String(1..8)
> begin
>   Label(1..8) == "12345678";
>   S := Interfaces.C.To_C(Label);
>  end;

Since you seem to be pretty new to Ada, I think you may have some
misconceptions about how arrays work; so it might be useful to go over
some basics.

Array objects (this includes Strings) have bounds.  Once the bounds
are set for an object, they don't change.  For Example, Label has the
bounds 1..8 since you've declared it that way.  You can't make Label
shorter or longer by saying, for instance,

   Label := "123456";

This will get you a Constraint_Error.  S also has bounds.  Since S is
a parameter with an unconstrained array type, the bounds of S are
determined by whatever parameter gets passed when Get_Text is called.
(That's why it's a problem when it's called from C, because C code
won't know that it's supposed to give any bounds to Get_Text.)  But
whatever the bounds are of the parameter are, they won't change; you
can't change the bounds, or make S longer or shorter, by assigning to
it.  That means that in your statement:

   S := Interfaces.C.To_C (Label);

The right-hand side will be an array with 9 characters (since Label
has 8, and To_C appends a NUL character).  This statement will
therefore work only if S's bounds are such that S will have exactly 9
characters.  (I.e. if S's bounds are (1..9), (3..11), (100..108),
etc.)  Otherwise it will raise Constraint_Error.

By the way, that applies to OUT parameters just as well as IN and IN
OUT parameters.  For an unconstrained array, OUT means that the data
in the array will be set by the procedure.  But the *bounds* of the
array parameter are still input to the procedure, not output from it,
and the procedure can't change them.

If you need to set a portion of S, you need to use a slice on the
left:

  S (S'First .. S'First + Label'Length) := Interfaces.C.To_C (Label);

which takes advantage of the knowledge that To_C returns a string
whose length is Label'Length + 1.  Or there are operations in
Ada.Strings.Fixed to help with this:

  Ada.Strings.Fixed.Overwrite (S, S'First, Interfaces.C.To_C (Label));

Hope this helps,

                         -- Adam



  parent reply	other threads:[~2011-11-19  2:18 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-18 19:40 Calling Ada Procedure from C - how to handle a char ptr/array awdorrin
2011-11-18 19:56 ` Jeffrey Carter
2011-11-18 20:19   ` awdorrin
2011-11-18 20:41     ` awdorrin
2011-11-18 21:38       ` Adam Beneschan
2011-11-18 22:32       ` Georg Bauhaus
2011-11-19  2:16 ` Adam Beneschan [this message]
2011-11-21 16:33   ` awdorrin
2011-11-22 13:20     ` awdorrin
2011-11-22 13:28       ` Simon Wright
replies disabled

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