comp.lang.ada
 help / color / mirror / Atom feed
* Interfacing with C - pointer problem
@ 2007-01-30 14:23 Gerd
  2007-01-30 15:53 ` Frank J. Lhota
  2007-01-30 21:10 ` tmoran
  0 siblings, 2 replies; 5+ messages in thread
From: Gerd @ 2007-01-30 14:23 UTC (permalink / raw)


I try to call some C code, so I wrote me a simple interface, but it 
does not what I expected.

It looks like this:

  type LPSTR is access all String;

  procedure C_Func (x : LPSTR);  -- expects an address (C-pointer, 32-
bit)
  pragma Import (STDCALL, C_Func, "C_Func");

  procedure Q is
   data : aliased String := "ABC" & Ascii.Nul;

  begin
   C_Func (data'unchecked_access);
  end Q;

This does not work correct. What I found is, that data'Address is 32 
bit and LPSTR is 64 bit.

How to manage this?

I tried a "pragma Convention (C, LPSTR);" but this gives a warning. So 
what would be the right way?

Thanks in advance,
Gerd




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

* Re: Interfacing with C - pointer problem
  2007-01-30 14:23 Interfacing with C - pointer problem Gerd
@ 2007-01-30 15:53 ` Frank J. Lhota
  2007-01-30 21:10 ` tmoran
  1 sibling, 0 replies; 5+ messages in thread
From: Frank J. Lhota @ 2007-01-30 15:53 UTC (permalink / raw)


Try using the Interfaces.C.Strings facilities instead. 





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

* Re: Interfacing with C - pointer problem
  2007-01-30 14:23 Interfacing with C - pointer problem Gerd
  2007-01-30 15:53 ` Frank J. Lhota
@ 2007-01-30 21:10 ` tmoran
  2007-01-31 18:10   ` Adam Beneschan
  1 sibling, 1 reply; 5+ messages in thread
From: tmoran @ 2007-01-30 21:10 UTC (permalink / raw)


>   type LPSTR is access all String;
>
> This does not work correct. What I found is, that data'Address is 32
> bit and LPSTR is 64 bit.
   Because LPSTR points to a dynamic size string and thus needs to
carry along bounds information.  A C LPSTR does not point to a dynamic
string, but instead points to a single character - the first in the
string.  So the match is
   type LPSTR is access Interfaces.C.Char;
   procedure C_Func (x : LPSTR);  -- expects an address (C-pointer, 32-bit)
and then
   data : Interfaces.C.char_array := Interfaces.C.To_C("ABC");
and
   C_Func (data(data'first)'unchecked_access);



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

* Re: Interfacing with C - pointer problem
  2007-01-30 21:10 ` tmoran
@ 2007-01-31 18:10   ` Adam Beneschan
  2007-01-31 23:53     ` Jeffrey R. Carter
  0 siblings, 1 reply; 5+ messages in thread
From: Adam Beneschan @ 2007-01-31 18:10 UTC (permalink / raw)


On Jan 30, 1:10 pm, tmo...@acm.org wrote:
> >   type LPSTR is access all String;
>
> > This does not work correct. What I found is, that data'Address is 32
> > bit and LPSTR is 64 bit.
>
>    Because LPSTR points to a dynamic size string and thus needs to
> carry along bounds information.  A C LPSTR does not point to a dynamic
> string, but instead points to a single character - the first in the
> string.  So the match is
>    type LPSTR is access Interfaces.C.Char;
>    procedure C_Func (x : LPSTR);  -- expects an address (C-pointer, 32-bit)
> and then
>    data : Interfaces.C.char_array := Interfaces.C.To_C("ABC");
> and
>    C_Func (data(data'first)'unchecked_access);

Or perhaps better:

   procedure C_Func (x : Interfaces.C.Strings.chars_ptr);

   data : aliased Interfaces.C.char_array := Interfaces.C.To_C
("ABC");

   C_Func (Interfaces.C.Strings.To_Chars_Ptr (data'unchecked_access));

May as well use the stuff Ada provides for this exact purpose.

                          -- Adam




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

* Re: Interfacing with C - pointer problem
  2007-01-31 18:10   ` Adam Beneschan
@ 2007-01-31 23:53     ` Jeffrey R. Carter
  0 siblings, 0 replies; 5+ messages in thread
From: Jeffrey R. Carter @ 2007-01-31 23:53 UTC (permalink / raw)


Adam Beneschan wrote:
>>    type LPSTR is access Interfaces.C.Char;
>>    procedure C_Func (x : LPSTR);  -- expects an address (C-pointer, 32-bit)
>> and then
>>    data : Interfaces.C.char_array := Interfaces.C.To_C("ABC");
>> and
>>    C_Func (data(data'first)'unchecked_access);
> 
> Or perhaps better:
> 
>    procedure C_Func (x : Interfaces.C.Strings.chars_ptr);
> 
>    data : aliased Interfaces.C.char_array := Interfaces.C.To_C
> ("ABC");
> 
>    C_Func (Interfaces.C.Strings.To_Chars_Ptr (data'unchecked_access));
> 
> May as well use the stuff Ada provides for this exact purpose.

Right. Therefore, even better:

procedure C_Func (X : in Interfaces.C.Char_Array);
pragma Import (C, C_Func, ...);

Data : Interfaces.C.Char_Array := Interfaces.C.To_C ("ABC);

C_Func (X => Data);

The language passes this a a pointer to Data (Data'First). See ARM B.3 
(70): "An Ada parameter of an array type with component type T, of any 
mode, is passed as a t* argument to a C function, where t is the C type 
corresponding to the Ada type T."

-- 
Jeff Carter
"Alms for an ex-leper!"
Monty Python's Life of Brian
75



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

end of thread, other threads:[~2007-01-31 23:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-30 14:23 Interfacing with C - pointer problem Gerd
2007-01-30 15:53 ` Frank J. Lhota
2007-01-30 21:10 ` tmoran
2007-01-31 18:10   ` Adam Beneschan
2007-01-31 23:53     ` Jeffrey R. Carter

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