comp.lang.ada
 help / color / mirror / Atom feed
* Converting pointers to non nul-terminated C "strings" to Ada string
@ 2009-02-14  6:58 xorquewasp
  2009-02-14  9:26 ` Dmitry A. Kazakov
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: xorquewasp @ 2009-02-14  6:58 UTC (permalink / raw)


Hello.

I have some C code that returns a pointer to a buffer of
"data" (not a string, just raw data) and also returns the
size of the buffer:

void
get_data (char **ptr, int *size);

int size;
char *ptr;

get_data (&ptr, &size);

The code is part of a library that I don't control, so I can't
change the interface.

I've defined the Ada equivalent as:

    package CS renames Interfaces.C.Strings;
    package C renames Interfaces.C;

    procedure memory_data
      (data   : out CS.chars_ptr;
       size   : out C.int);
    pragma Import (C, memory_data, "get_data");

This works correctly, however I'm having trouble converting
the chars_ptr type to an Ada string given that it's not nul-
terminated.

Attempts to do the following:

return CS.Value (Item => data, Length => size);

... results in a String as long as the position of the first nul in
the
C string (the position is inevitably less than the length of the
string).

Is it possible to properly convert unterminated C strings or do I
need to start messing about with raw System.Address types?



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  6:58 Converting pointers to non nul-terminated C "strings" to Ada string xorquewasp
@ 2009-02-14  9:26 ` Dmitry A. Kazakov
  2009-02-14 10:38   ` xorquewasp
  2009-02-14  9:27 ` Hibou57 (Yannick Duchêne)
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 12+ messages in thread
From: Dmitry A. Kazakov @ 2009-02-14  9:26 UTC (permalink / raw)


On Fri, 13 Feb 2009 22:58:55 -0800 (PST), xorquewasp@googlemail.com wrote:

> I have some C code that returns a pointer to a buffer of
> "data" (not a string, just raw data) and also returns the
> size of the buffer:
> 
> void
> get_data (char **ptr, int *size);
> 
> int size;
> char *ptr;
> 
> get_data (&ptr, &size);
> 
> The code is part of a library that I don't control, so I can't
> change the interface.
> 
> I've defined the Ada equivalent as:
> 
>     package CS renames Interfaces.C.Strings;
>     package C renames Interfaces.C;
> 
>     procedure memory_data
>       (data   : out CS.chars_ptr;
>        size   : out C.int);
>     pragma Import (C, memory_data, "get_data");
> 
> This works correctly, however I'm having trouble converting
> the chars_ptr type to an Ada string given that it's not nul-
> terminated.
> 
> Attempts to do the following:
> 
> return CS.Value (Item => data, Length => size);
> 
> ... results in a String as long as the position of the first nul in
> the
> C string (the position is inevitably less than the length of the
> string).
> 
> Is it possible to properly convert unterminated C strings or do I
> need to start messing about with raw System.Address types?

I would suggest to use Interfaces.C.Pointers instead of
Interfaces.C.Strings:

with Interfaces.C;           use Interfaces.C;
with Interfaces.C.Pointers;

package Char_Ptrs is
   new Interfaces.C.Pointers (size_t, char, char_array, Nul);
use Char_Ptrs;

function Get return String is
   procedure memory_data
             (  data   : out Pointer;
                size   : out ptrdiff_t  -- Really int as in your example?
             );
   pragma Import (C, memory_data, "get_data");
   Data : Pointer;
   Size : ptrdiff_t;
begin
   memory_data (Data, Size);
   return To_Ada (Value (Data, Size), False);
end Get;

Are you sure that get_data is char **, int * rather than void **, size_t *?
In the latter case I would consider Storage_Array instead of String on the
Ada side.

Yet another issue. It is not so frequent that C API allocated a data buffer
and returned it to the caller, as your example suggests. Usually it is the
caller who passes an array to the C callee specifying its maximal capacity.
In this case the code should be different. In the former case, the question
arise, who is responsible for feeing the buffer. Does Data point to some
statically allocated piece of memory inside C library, or else you have to
free Data after converting it to Ada array?

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



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  6:58 Converting pointers to non nul-terminated C "strings" to Ada string xorquewasp
  2009-02-14  9:26 ` Dmitry A. Kazakov
@ 2009-02-14  9:27 ` Hibou57 (Yannick Duchêne)
  2009-02-14 10:41   ` xorquewasp
  2009-02-14 11:47   ` Jacob Sparre Andersen
  2009-02-14  9:28 ` sjw
  2009-02-14  9:33 ` likai3g
  3 siblings, 2 replies; 12+ messages in thread
From: Hibou57 (Yannick Duchêne) @ 2009-02-14  9:27 UTC (permalink / raw)




xorquew...@googlemail.com a écrit :
> Hello.
Hi, :-)

A dirty thing which comes into my mind : when you write

procedure memory_data
      (data   : out CS.chars_ptr;
       size   : out C.int);

you may doing some assumption about the the compiler's generated code.
In my humble opinion, pointers in C declarations should be mapped to
access types in Ada. There is nothing I know which assert that an Ada
implementation must use access types to implement out parameters.

> ... results in a String as long as the position of the first nul in
> the
> C string (the position is inevitably less than the length of the
> string).
 > Is it possible to properly convert unterminated C strings or do I
> need to start messing about with raw System.Address types?

If the returned string may have null characters before its last index,
this means it is a string which contains null characters as its
character datas, so it is not C string.

By the way, what does the null character stands for within these
strings ? Is it interpreted as a graphical character or as command
character ? What is supposed to be the string encoding ? ANSI ?
Windows CP ? UTF-8 ?

To know how to properly handle this, the first requirements is to
exactly know what does datas stands for.

Have a nice sunday

Y.D.



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  6:58 Converting pointers to non nul-terminated C "strings" to Ada string xorquewasp
  2009-02-14  9:26 ` Dmitry A. Kazakov
  2009-02-14  9:27 ` Hibou57 (Yannick Duchêne)
@ 2009-02-14  9:28 ` sjw
  2009-02-14  9:33 ` likai3g
  3 siblings, 0 replies; 12+ messages in thread
From: sjw @ 2009-02-14  9:28 UTC (permalink / raw)


On Feb 14, 6:58 am, xorquew...@googlemail.com wrote:

> Is it possible to properly convert unterminated C strings or do I
> need to start messing about with raw System.Address types?

I think you may need this from Interfaces.C (after all, what you're
looking at isn't a C string, which is what Interfaces.C.Strings is
for).

   function To_Ada
     (Item     : char_array;
      Trim_Nul : Boolean := True) return String;

You'll need to define your own pointer-to-Interfaces.C.char_array, I
think.



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  6:58 Converting pointers to non nul-terminated C "strings" to Ada string xorquewasp
                   ` (2 preceding siblings ...)
  2009-02-14  9:28 ` sjw
@ 2009-02-14  9:33 ` likai3g
  3 siblings, 0 replies; 12+ messages in thread
From: likai3g @ 2009-02-14  9:33 UTC (permalink / raw)


On 2月14日, 下午2时58分, xorquew...@googlemail.com wrote:
> Hello.
>
> I have some C code that returns a pointer to a buffer of
> "data" (not a string, just raw data) and also returns the
> size of the buffer:
>
> void
> get_data (char **ptr, int *size);
>
> int size;
> char *ptr;
>
> get_data (&ptr, &size);
>
> The code is part of a library that I don't control, so I can't
> change the interface.
>
> I've defined the Ada equivalent as:
>
>     package CS renames Interfaces.C.Strings;
>     package C renames Interfaces.C;
>
>     procedure memory_data
>       (data   : out CS.chars_ptr;
>        size   : out C.int);
>     pragma Import (C, memory_data, "get_data");
>
> This works correctly, however I'm having trouble converting
> the chars_ptr type to an Ada string given that it's not nul-
> terminated.
>
> Attempts to do the following:
>
> return CS.Value (Item => data, Length => size);
>
> ... results in a String as long as the position of the first nul in
> the
> C string (the position is inevitably less than the length of the
> string).
>
> Is it possible to properly convert unterminated C strings or do I
> need to start messing about with raw System.Address types?
--try this....
   declare
      subtype Huge is String(Positive);
      type PHuge is access all Huge;
      type CString is record
	 Data: PHuge;
	 Size: Natural;
      end record;
      pragma Convention(C_Pass_By_Copy, CString);
      procedure Get_Data(S: out CString);
      pragma Import(C, Get_Data, "get_data");
      S: CString;
   begin
      Get_Data(S);
      Ada.Text_IO.Put_Line(S.Data(1..S.Size));
   end;



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  9:26 ` Dmitry A. Kazakov
@ 2009-02-14 10:38   ` xorquewasp
  2009-02-14 11:16     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 12+ messages in thread
From: xorquewasp @ 2009-02-14 10:38 UTC (permalink / raw)




Dmitry A. Kazakov wrote:
>
> I would suggest to use Interfaces.C.Pointers instead of
> Interfaces.C.Strings:
>

That does mean going outside of the RM, which is a bit unfortunate.
I'll keep it in mind, however.

>
> Are you sure that get_data is char **, int * rather than void **, size_t *?
> In the latter case I would consider Storage_Array instead of String on the
> Ada side.

Well, the C function parameters are defined as char **, int * but do
have
a meaning closer to void **, size_t *. Storage_Array is probably more
appropriate, as you state. That still leaves the question of
converting from
an address or access type to an unconstrained array (can't pass an
unconstrained array or access to an unconstrained array to C code).

>
> Yet another issue. It is not so frequent that C API allocated a data buffer
> and returned it to the caller, as your example suggests.

In this case, the library remains in complete control of the memory.

(It's one of the OpenSSL bio.h functions, if anyone's really curious).



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  9:27 ` Hibou57 (Yannick Duchêne)
@ 2009-02-14 10:41   ` xorquewasp
  2009-02-15 17:44     ` Georg Bauhaus
  2009-02-14 11:47   ` Jacob Sparre Andersen
  1 sibling, 1 reply; 12+ messages in thread
From: xorquewasp @ 2009-02-14 10:41 UTC (permalink / raw)


Yannick Duchêne Hibou57 wrote:
>
> A dirty thing which comes into my mind : when you write
>
> procedure memory_data
>       (data   : out CS.chars_ptr;
>        size   : out C.int);
>
> you may doing some assumption about the the compiler's generated code.
> In my humble opinion, pointers in C declarations should be mapped to
> access types in Ada. There is nothing I know which assert that an Ada
> implementation must use access types to implement out parameters.

I may indeed. In most cases, I would use access types. I do extremely
heavy unit testing and haven't found a compiler/OS/arch combo where
the
above example doesn't work correctly, however.

> To know how to properly handle this, the first requirements is to
> exactly know what does datas stands for.

It's strictly a binary blob - the output of an encryption function.

> Have a nice sunday

Likewise!



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14 10:38   ` xorquewasp
@ 2009-02-14 11:16     ` Dmitry A. Kazakov
  2009-02-14 11:37       ` xorquewasp
  0 siblings, 1 reply; 12+ messages in thread
From: Dmitry A. Kazakov @ 2009-02-14 11:16 UTC (permalink / raw)


On Sat, 14 Feb 2009 02:38:35 -0800 (PST), xorquewasp@googlemail.com wrote:

> Dmitry A. Kazakov wrote:
>>
>> I would suggest to use Interfaces.C.Pointers instead of
>> Interfaces.C.Strings:
> 
> That does mean going outside of the RM, which is a bit unfortunate.
> I'll keep it in mind, however.

What do you mean by that? Interfaces.C.Pointers is a part of the standard
Ada library.

>> Are you sure that get_data is char **, int * rather than void **, size_t *?
>> In the latter case I would consider Storage_Array instead of String on the
>> Ada side.
> 
> Well, the C function parameters are defined as char **, int * but do have
> a meaning closer to void **, size_t *. Storage_Array is probably more
> appropriate, as you state. That still leaves the question of
> converting from an address or access type to an unconstrained array (can't pass an
> unconstrained array or access to an unconstrained array to C code).

One technique is to declare a huge flat array:

   type Never_Instantiate_Me is array (size_t'range) of char;
   pragma Convention (C, Never_Instantiate_Me);

or else simply:

   subtype Never_Instantiate_Me is char_array (size_t'range);

Never_Instantiate_Me will have no dope.

   type Never_Instantiate_Me_Ptr is access all Never_Instantiate_Me;
   pragma Convention (C, Never_Instantiate_Me_Ptr);;

Then you go:

   function Get return String is
      procedure memory_data
                (  data   : out Never_Instantiate_Me_Ptr;
                   size   : out size_t
                );
      pragma Import (C, memory_data, "get_data");
      Data : Never_Instantiate_Me_Ptr;
      Size : size_t;
   begin
      memory_data (Data, Size);
      if Size = 0 then
         return "";
      else
         return
            To_Ada
            (  Data (size_t'First..size_t'First + Size - 1),
               False
            );
      end if;
   end Get;

Note Size = 0 check. When Size is zero, there is no way to construct an
empty char_array since size_t is modular.
 
-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14 11:16     ` Dmitry A. Kazakov
@ 2009-02-14 11:37       ` xorquewasp
  0 siblings, 0 replies; 12+ messages in thread
From: xorquewasp @ 2009-02-14 11:37 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Sat, 14 Feb 2009 02:38:35 -0800 (PST), xorquewasp@googlemail.com wrote:
> > That does mean going outside of the RM, which is a bit unfortunate.
> > I'll keep it in mind, however.
>
> What do you mean by that? Interfaces.C.Pointers is a part of the standard
> Ada library.

Sorry, I was thinking of Interfaces.C.Extensions.

> One technique is to declare a huge flat array:
>

Thanks for that. I'll try it.



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  9:27 ` Hibou57 (Yannick Duchêne)
  2009-02-14 10:41   ` xorquewasp
@ 2009-02-14 11:47   ` Jacob Sparre Andersen
  2009-02-14 14:25     ` Hibou57 (Yannick Duchêne)
  1 sibling, 1 reply; 12+ messages in thread
From: Jacob Sparre Andersen @ 2009-02-14 11:47 UTC (permalink / raw)


Yannick Duch�ne wrote:

> A dirty thing which comes into my mind : when you write
>
> procedure memory_data
>       (data   : out CS.chars_ptr;
>        size   : out C.int);
>
> you may doing some assumption about the the compiler's generated
> code.  In my humble opinion, pointers in C declarations should be
> mapped to access types in Ada. There is nothing I know which assert
> that an Ada implementation must use access types to implement out
> parameters.

RM95 B.3(68) comes to mind.

Greetings,

Jacob
-- 
Ada - the programming language still ahead of its time.



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14 11:47   ` Jacob Sparre Andersen
@ 2009-02-14 14:25     ` Hibou57 (Yannick Duchêne)
  0 siblings, 0 replies; 12+ messages in thread
From: Hibou57 (Yannick Duchêne) @ 2009-02-14 14:25 UTC (permalink / raw)


On 14 fév, 12:47, Jacob Sparre Andersen <spa...@nbi.dk> wrote:
> RM95 B.3(68) comes to mind.
>
> Greetings,
>
> Jacob
> --
> Ada - the programming language still ahead of its time.

Right Jacob

It says

“ An Ada access T parameter, or an Ada out or in out parameter of an
elementary type T, is passed as a t* argument to a C function, where t
is the C type corresponding to the Ada type T. In the case of an
elementary out or in out parameter, a pointer to a temporary copy is
used to preserve by-copy semantics. ”

Thanks for the material

Greetings as well

Y.D.



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

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14 10:41   ` xorquewasp
@ 2009-02-15 17:44     ` Georg Bauhaus
  0 siblings, 0 replies; 12+ messages in thread
From: Georg Bauhaus @ 2009-02-15 17:44 UTC (permalink / raw)


xorquewasp@googlemail.com wrote:
> Yannick Duch�ne Hibou57 wrote:
>> A dirty thing which comes into my mind : when you write
>>
>> procedure memory_data
>>       (data   : out CS.chars_ptr;
>>        size   : out C.int);
>>
>> you may doing some assumption about the the compiler's generated code.
>> In my humble opinion, pointers in C declarations should be mapped to
>> access types in Ada. There is nothing I know which assert that an Ada
>> implementation must use access types to implement out parameters.
> 
> I may indeed. In most cases, I would use access types. I do extremely
> heavy unit testing and haven't found a compiler/OS/arch combo where
> the
> above example doesn't work correctly, however.
> 
>> To know how to properly handle this, the first requirements is to
>> exactly know what does datas stands for.
> 
> It's strictly a binary blob - the output of an encryption function.


Some of the issues are adressed in "Accessing Memory as a String",
http://www.adapower.com/index.php?Command=Class&ClassID=Advanced&CID=213
The article answers the question,

"How do I access a chunck of memory as an Ada string with out
moving or copying the data in Ada95?"

Maybe you can use the size parameter for specifying an
index subtype that porperly constrains the string.



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

end of thread, other threads:[~2009-02-15 17:44 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-14  6:58 Converting pointers to non nul-terminated C "strings" to Ada string xorquewasp
2009-02-14  9:26 ` Dmitry A. Kazakov
2009-02-14 10:38   ` xorquewasp
2009-02-14 11:16     ` Dmitry A. Kazakov
2009-02-14 11:37       ` xorquewasp
2009-02-14  9:27 ` Hibou57 (Yannick Duchêne)
2009-02-14 10:41   ` xorquewasp
2009-02-15 17:44     ` Georg Bauhaus
2009-02-14 11:47   ` Jacob Sparre Andersen
2009-02-14 14:25     ` Hibou57 (Yannick Duchêne)
2009-02-14  9:28 ` sjw
2009-02-14  9:33 ` likai3g

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