comp.lang.ada
 help / color / mirror / Atom feed
* Returning a string from C
@ 2015-07-23  2:20 NiGHTS
  2015-07-23  4:48 ` Jeffrey R. Carter
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: NiGHTS @ 2015-07-23  2:20 UTC (permalink / raw)


I am having some difficulty with returning a string from a C function.

Say I have the following C function:

    void Return_Hello (char *inout_Test_String ) {
        strcpy( inout_Test_String, "Hello World" );
    }

This function will use the string memory generated on the Ada side and return a simple string "Hello World". Here is how I would interface with it:

    procedure Return_Hello ( Test_String : in out chars_ptr );
    pragma Import (C, Return_Hello, "Return_Hello");

And this is how I would use it.

    use Interfaces.C;
    use Interfaces.C.Strings;

    declare

        Test_String      : String (1 .. 100);
        Test_String_Char : chars_ptr := New_String (Test_String);

    begin
    
        Return_Hello ( Test_String_Char );
        Test_String := Value ( Test_String_Char ) ;
        Ada.Text_IO.Put_Line ( Test_String );
        Free (Test_String_Char);
  
    end;

When I run the program I get a runtime error "length check failed" on the line "Test_String := Value ( Test_String_Char );".

What am I doing wrong here?

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

* Re: Returning a string from C
  2015-07-23  2:20 Returning a string from C NiGHTS
@ 2015-07-23  4:48 ` Jeffrey R. Carter
  2015-07-23  4:54 ` Per Sandberg
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Jeffrey R. Carter @ 2015-07-23  4:48 UTC (permalink / raw)


On 07/22/2015 07:20 PM, NiGHTS wrote:
> 
> Say I have the following C function:
> 
>     void Return_Hello (char *inout_Test_String ) {
>         strcpy( inout_Test_String, "Hello World" );
>     }
> 
> This function will use the string memory generated on the Ada side and return a simple string "Hello World". Here is how I would interface with it:
> 
>     procedure Return_Hello ( Test_String : in out chars_ptr );
>     pragma Import (C, Return_Hello, "Return_Hello");
> 
> And this is how I would use it.
> 
>     use Interfaces.C;
>     use Interfaces.C.Strings;
> 
>     declare
> 
>         Test_String      : String (1 .. 100);
>         Test_String_Char : chars_ptr := New_String (Test_String);
> 
>     begin
>     
>         Return_Hello ( Test_String_Char );
>         Test_String := Value ( Test_String_Char ) ;
>         Ada.Text_IO.Put_Line ( Test_String );
>         Free (Test_String_Char);
>   
>     end;
> 
> When I run the program I get a runtime error "length check failed" on the line "Test_String := Value ( Test_String_Char );".
> 
> What am I doing wrong here?

Well, for one thing, you're thinking like a C person and using unnecessary
pointers. I'd import the procedure as

procedure Return_Hello (Test_String : out Char_Array);

and call it with

Test_String : Char_Array (1 .. 100);

Return_Hello (Test_String => Test_String);
Ada.Text_IO.Put_Line (Item => To_Ada (Test_String) );

As for the exception you get, Value returns the string pointed to by Item up to
but not including the terminating NUL, which is 11 characters. Test_String is
100 characters, so the lengths don't match.

-- 
Jeff Carter
"Sir Robin the not-quite-so-brave-as-Sir-Lancelot,
who had nearly fought the Dragon of Angnor,
who nearly stood up to the vicious Chicken of Bristol,
and who had personally wet himself at the
Battle of Badon Hill."
Monty Python & the Holy Grail
68


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

* Re: Returning a string from C
  2015-07-23  2:20 Returning a string from C NiGHTS
  2015-07-23  4:48 ` Jeffrey R. Carter
@ 2015-07-23  4:54 ` Per Sandberg
  2015-07-23  4:58 ` Laurent
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Per Sandberg @ 2015-07-23  4:54 UTC (permalink / raw)


Fairly simple:
Since the strings in Ada has length you cant use direct assignment with 
strings of different lengths.

just replace:
    Test_String := Value ( Test_String_Char );
with:
    Ada.Strings.Fixed.Move(Value(Test_String_Char), Test_String);

That will take care of the differences in Length and do the
   padding/trunking/failing/justification

depending on extra parameters to Move.

/Per


Den 2015-07-23 04:20, NiGHTS skrev:
>   Test_String := Value ( Test_String_Char ) ;


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

* Returning a string from C
  2015-07-23  2:20 Returning a string from C NiGHTS
  2015-07-23  4:48 ` Jeffrey R. Carter
  2015-07-23  4:54 ` Per Sandberg
@ 2015-07-23  4:58 ` Laurent
  2015-07-23  6:41 ` Pascal Obry
  2015-07-23  7:17 ` Dmitry A. Kazakov
  4 siblings, 0 replies; 6+ messages in thread
From: Laurent @ 2015-07-23  4:58 UTC (permalink / raw)


Test_String is of Length 100. So it expects a string exactly this length.
When you try to assign the string "Hello World", you get a length error because it is to short.

Unfortunately I am only a noob and I have quite a hard time with the standard strings myself. 

You could try Test_String : String; so it is not constrained but I don't think that the compiler accepts. Tried that already with my own programms. Sometimes it works but not always. 

Of course I could be completely wrong.

Laurent

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

* Re: Returning a string from C
  2015-07-23  2:20 Returning a string from C NiGHTS
                   ` (2 preceding siblings ...)
  2015-07-23  4:58 ` Laurent
@ 2015-07-23  6:41 ` Pascal Obry
  2015-07-23  7:17 ` Dmitry A. Kazakov
  4 siblings, 0 replies; 6+ messages in thread
From: Pascal Obry @ 2015-07-23  6:41 UTC (permalink / raw)


Le mercredi 22 juillet 2015 à 19:20 -0700, NiGHTS a écrit :
> I am having some difficulty with returning a string from a C 
> function.
> 
> Say I have the following C function:
> 
>     void Return_Hello (char *inout_Test_String ) {
>         strcpy( inout_Test_String, "Hello World" );
>     }

I would probably also pass the string length here and use strlcpy
instead to avoid any memory corruption.

-- 
  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] 6+ messages in thread

* Re: Returning a string from C
  2015-07-23  2:20 Returning a string from C NiGHTS
                   ` (3 preceding siblings ...)
  2015-07-23  6:41 ` Pascal Obry
@ 2015-07-23  7:17 ` Dmitry A. Kazakov
  4 siblings, 0 replies; 6+ messages in thread
From: Dmitry A. Kazakov @ 2015-07-23  7:17 UTC (permalink / raw)


On Wed, 22 Jul 2015 19:20:34 -0700 (PDT), NiGHTS wrote:

> I am having some difficulty with returning a string from a C function.
> 
> Say I have the following C function:
> 
>     void Return_Hello (char *inout_Test_String ) {
>         strcpy( inout_Test_String, "Hello World" );
>     }

[...]

> What am I doing wrong here?

When you pass a string to C, use To_C from Interfaces.C that returns
char_array

 When you receive a string from C, use Chars_Ptr and Value from
Interfaces.C.Strings. E.g.

   function Foo (Text : String) return String is
      function Internal (S : char_array) return Chars_Ptr;
      pragma Import (C, Internal, "c_stuff");
      Result : Chars_Ptr;
   begin
      Result := Internal (To_C (Text));
      if Result /= Null_Ptr then
         return Value (Result);
      else
         return "";
      end if;
   end Foo;

When C side allocates a new string and your side is responsible for
deallocating it, use Free on Chars_Ptr from Interfaces.C.Strings.

If you want in-place string modified by C, pass char_array, maximum size,
actual length to C.

Never ever use strcpy, always strncpy.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

end of thread, other threads:[~2015-07-23  7:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-23  2:20 Returning a string from C NiGHTS
2015-07-23  4:48 ` Jeffrey R. Carter
2015-07-23  4:54 ` Per Sandberg
2015-07-23  4:58 ` Laurent
2015-07-23  6:41 ` Pascal Obry
2015-07-23  7:17 ` Dmitry A. Kazakov

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