comp.lang.ada
 help / color / mirror / Atom feed
* Interface to C; Storage_Error
@ 2000-12-19 22:28 Chris
  2000-12-20  3:52 ` Ted Dennison
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Chris @ 2000-12-19 22:28 UTC (permalink / raw)


Hi, all... after a long hiatus in the C++ world, I'm finally getting a
chance to do some more Ada work, at my own suggestion. The ability to
write production-quality multithread code an order of magnitude faster
in Ada might have something to do with it.

Anyway, I'm having an irritating problem interfacing with a vendor C
library. The relevant stuff:

  typedef void* SRV_HANDLE;
  typedef void* CTX_HANDLE;
  typedef void* RSLT_HANDLE;
  typedef void* FLT_HANDLE;

   int GetNextVal(SRV_HANDLE srv, RSLT_HANDLE rslt, CTX_HANDLE *ctx,
                  char* name, double* dbl, FLT_HANDLE flt);

My take on it in Ada (GNAT 3.13p) is:

   type Srv_Handle is new System.Address;
   -- same for the other handles

   procedure GetNextVal(Ret  : out int;
                        Srv  : Srv_Handle;
                        Rslt : Rslt_Handle;
                        Ctx  : access Ctx_Handle;
                        Name : out chars_ptr;
                        Dbl  : access double;
                        Flt : Flt_Handle);
   pragma Import(C, GetNextVal);
   pragma Import_Valued_Procedure(GetNextVal);

Both Name and Dbl are supposedly set/alloc'd by the library. When I
call this, it raises Storage_Error on the library call. I am totally
stumped as to what to fix, or even where to look. Is my Ada declaration
even remotely correct?
Other suggestions?


Many thanks.

--chris


Sent via Deja.com
http://www.deja.com/



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

* Re: Interface to C; Storage_Error
  2000-12-19 22:28 Interface to C; Storage_Error Chris
@ 2000-12-20  3:52 ` Ted Dennison
  2000-12-20  8:55   ` Robert Dewar
  2000-12-20 11:39 ` Thomas Wolf
  2000-12-21  3:25 ` DuckE
  2 siblings, 1 reply; 11+ messages in thread
From: Ted Dennison @ 2000-12-20  3:52 UTC (permalink / raw)


In article <91ondg$lpu$1@nnrp1.deja.com>,
  Chris <enderx12@my-deja.com> wrote:

>   typedef void* SRV_HANDLE;
>   typedef void* CTX_HANDLE;
>   typedef void* RSLT_HANDLE;
>   typedef void* FLT_HANDLE;
>
>    int GetNextVal(SRV_HANDLE srv, RSLT_HANDLE rslt, CTX_HANDLE *ctx,
>                   char* name, double* dbl, FLT_HANDLE flt);
>
> My take on it in Ada (GNAT 3.13p) is:
>
>    type Srv_Handle is new System.Address;
>    -- same for the other handles
>
>    procedure GetNextVal(Ret  : out int;
>                         Srv  : Srv_Handle;
>                         Rslt : Rslt_Handle;
>                         Ctx  : access Ctx_Handle;
>                         Name : out chars_ptr;
>                         Dbl  : access double;
>                         Flt : Flt_Handle);
>    pragma Import(C, GetNextVal);
>    pragma Import_Valued_Procedure(GetNextVal);
>
> Both Name and Dbl are supposedly set/alloc'd by the library. When I
> call this, it raises Storage_Error on the library call. I am totally
> stumped as to what to fix, or even where to look. Is my Ada declaration
> even remotely correct?
> Other suggestions?

One thing I should mention first off, is that pragma
Import_Valued_Procedure is a gnat-specific pragma (borrowed from the
late-great DECAda). If there is any chance at all that this code may
ever be ported to a different compiler, I would stick to pragma Import.

That brings me to the second issue; pragma Import does essentially the
same job as pragma Import_Valued_Procedure. Check the gnat docs, but it
seems wrong to me that they are being used together.

As for the rest, I'd need to see at least the call that is blowing up
(or is it a later use of one of the parameters that is blowing up?). The
interface description of that C call would be useful too. In my
experience that error is likely to occur because C (or the linkage
between them) is trying to dereference a null pointer or use a numeric
value as a pointer. But it could be that you are misusing a returned
pointer value. It could be that you didn't properly obtain one of those
handles...

--
T.E.D.

http://www.telepath.com/~dennison/Ted/TED.html


Sent via Deja.com
http://www.deja.com/



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

* Re: Interface to C; Storage_Error
  2000-12-20  3:52 ` Ted Dennison
@ 2000-12-20  8:55   ` Robert Dewar
  0 siblings, 0 replies; 11+ messages in thread
From: Robert Dewar @ 2000-12-20  8:55 UTC (permalink / raw)


In article <91padu$572$1@nnrp1.deja.com>,
  Ted Dennison <dennison@telepath.com> wrote:

> That brings me to the second issue; pragma Import does
> essentially th same job as pragma Import_Valued_Procedure.
> Check the gnat docs, but it seems wrong to me that they are
> being used together.

I suggest that if you want to offer advice on GNAT specific
pragmas, you read the GNAT documentation, rather than guessing,
since a completely wrong guess (as in this case) simply
confuses people. One of the troubles with CLA is that a
high proportion of the advice here is plain wrong.

In this particular case, a cursory check of the GNAT
documentation would have found the sentence:

 Note that it is important to use this pragma in conjunction
 with a separate pragma Import that specifies the desired
 convention, since otherwise the default convention is Ada,
 which is almost certainly not what is required.

Incidentally the use of pragma Import_Valued_Procedure is
perfectly reasonable in this case, and it is not so easily
replaced  by pragma Import alone (that's why DEC invented
this useful feature for interfacing to C).


Sent via Deja.com
http://www.deja.com/



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

* Re: Interface to C; Storage_Error
  2000-12-19 22:28 Interface to C; Storage_Error Chris
  2000-12-20  3:52 ` Ted Dennison
@ 2000-12-20 11:39 ` Thomas Wolf
  2000-12-20 17:05   ` Chris
  2000-12-21  3:25 ` DuckE
  2 siblings, 1 reply; 11+ messages in thread
From: Thomas Wolf @ 2000-12-20 11:39 UTC (permalink / raw)


On Tue, 19 Dec 2000 22:28:11 GMT, Chris <enderx12@my-deja.com> wrote:

>
>  typedef void* SRV_HANDLE;
>  typedef void* CTX_HANDLE;
>  typedef void* RSLT_HANDLE;
>  typedef void* FLT_HANDLE;
>
>   int GetNextVal(SRV_HANDLE srv, RSLT_HANDLE rslt, CTX_HANDLE *ctx,
>                  char* name, double* dbl, FLT_HANDLE flt);
>
>My take on it in Ada (GNAT 3.13p) is:
>
>   type Srv_Handle is new System.Address;
>   -- same for the other handles
>
>   procedure GetNextVal(Ret  : out int;
>                        Srv  : Srv_Handle;
>                        Rslt : Rslt_Handle;
>                        Ctx  : access Ctx_Handle;
>                        Name : out chars_ptr;
>                        Dbl  : access double;
>                        Flt : Flt_Handle);
>   pragma Import(C, GetNextVal);
>   pragma Import_Valued_Procedure(GetNextVal);
>
>Both Name and Dbl are supposedly set/alloc'd by the library. When I
>call this, it raises Storage_Error on the library call. I am totally
>stumped as to what to fix, or even where to look. Is my Ada declaration
>even remotely correct?

Name most certainly cannot be alloc'd by that C routine (it's a
"char *" passed by value). Your Ada interface however passes a 
"char **"...

I'd start there for looking for errors. What does the spec
(if it exists) for the C routine say about that argument? Is
it really a "char *"? If so, change the Ada declaration to
"Name : in chars_ptr". What does it have to point to upon entry?
What does the routine do with the memory pointed to? (How large
must the memory area pointed to by Name be?)

If the C routine really allocs Name, the C parameter type most
probably is "char **"...

--
Thomas Wolf
-- 
Dr. Thomas Wolf (twolf@acm.org)



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

* Re: Interface to C; Storage_Error
  2000-12-20 11:39 ` Thomas Wolf
@ 2000-12-20 17:05   ` Chris
  2000-12-20 23:57     ` Chris
  0 siblings, 1 reply; 11+ messages in thread
From: Chris @ 2000-12-20 17:05 UTC (permalink / raw)


In article <3a409667.1742507013@paragate1>,
  twolf@acm.org wrote:
> Name most certainly cannot be alloc'd by that C routine (it's a
> "char *" passed by value). Your Ada interface however passes a
> "char **"...
>
> I'd start there for looking for errors. What does the spec
> (if it exists) for the C routine say about that argument? Is
> it really a "char *"? If so, change the Ada declaration to
> "Name : in chars_ptr". What does it have to point to upon entry?
> What does the routine do with the memory pointed to? (How large
> must the memory area pointed to by Name be?)
>
> If the C routine really allocs Name, the C parameter type most
> probably is "char **"...

Argh. When all else fails, RTF.H carefully. Or at least the example
code. The spec doesn't actually spell it out, but Name is supposed to
be pointing to a 255-byte array of char.

What I'd like to do is have a semi-thick binding where users of the
package get ( ... Name : out String; Val : out double; ... ). So the
trick is to get the C function to fill a buffer I allocate in Ada, then
get that into an Ada String to send back to the caller.

So my initial thought is to declare the name parameter in the C
function as "in out char_array", then the wrapper function would return
its "Name := To_Ada(Name_Char_Array);". How does this sound?

Ugh, I hate C. If I wanted to program in assembler, I'd do so.

--chris



Sent via Deja.com
http://www.deja.com/



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

* Re: Interface to C; Storage_Error
  2000-12-20 17:05   ` Chris
@ 2000-12-20 23:57     ` Chris
  2000-12-21 15:35       ` Thomas Wolf
  0 siblings, 1 reply; 11+ messages in thread
From: Chris @ 2000-12-20 23:57 UTC (permalink / raw)


After trying many different configurations,
I now seem to be making negative progress. So
I'm going back to the C code and getting my
brain out of Ada for a few moments... in case
this helps someone make sense of what I should
do, here's what the code looks like in C:

  typedef void* SRV_HANDLE;
  typedef void* RSLT_HANDLE;
  typedef void* CTX_HANDLE;


  SRV_HANDLE hand = 0;
  RSLT_HANDLE results;
  CTX_HANDLE ctx = 0;
  char name[255];
  double value = 0.0;

  status = InititalizeLibrary("config.txt", &hand);
  // omitting error checking here
  status = LookupResults(hand, "keystring", &results);
  // reset these after every lookup
  ctx = 0;
  name[0] = 0;
  status = GetNextVal(hand, results, &ctx, name, &value);
  // this call can be repeated to get a series of name/value
  // pairs. ctx is the handle to keep track of repeated
  // calls, and starts at the beginning when 0.

Clear as mud? I'm stumped, and sad that my Ada is so rusty.

--chris


Sent via Deja.com
http://www.deja.com/



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

* Re: Interface to C; Storage_Error
  2000-12-19 22:28 Interface to C; Storage_Error Chris
  2000-12-20  3:52 ` Ted Dennison
  2000-12-20 11:39 ` Thomas Wolf
@ 2000-12-21  3:25 ` DuckE
  2000-12-21 11:38   ` Robert Dewar
  2 siblings, 1 reply; 11+ messages in thread
From: DuckE @ 2000-12-21  3:25 UTC (permalink / raw)


Here's my semi-educated "guess" at the interface to this function:

  package C renames Interfaces.C;

  subtype Srv_Handle is C.Unsigned_Long;         -- Assumes type for
"Handle" is Unsigned_Long
  type Ctx_Handle is access all C.Unsigned_Long; -- Assumes type for
"Ctx_Handle" is Unsigned_Long
  subtype Flt_Handle is C.C_Float;               -- Assumes type for
"Flt_Handle"

  function GetNextVal( srv : access Srv_Handle;
                       rslt : access Srv_Handle;
                       ctx  : access Ctx_Handle;
                       name : C.Char_Array;
                       dbl  : access C.Double;
                       flt  : access Flt_Handle ) return C.Int;
  pragma Import( C, GetNextVal );

Since the "C" prototype is using "char *" I suspect you need to allocate the
data to send to the
function.  I suspect a call would look something like:

-- (untested)
  srv : aliased Srv_Handle;
  rslt : aliased Srv_Handle;
  ctx : aliased Ctx_Handle;
  name : C.Char_Array := C.To_C( "Name" );
  dbl : aliased C.Double;
  flt : aliased Flt_Handle;
  result : C.Int;
begin
  result := GetNextVal( srv => srv'access,
                    rslt => rslt'access,
                    ctx => ctx'access,
                    name => name,
                    dbl => dbl'access,
                    flt => flt'access );

In my experience there is often more than one choice of how to interface to
C code.  I usually
stay away from System.Addres, although it is certainly valid to use, I
prefer to avoid it.

BTW: It was a challenge to interface to the RSLinx 'C' SDK, but I eventually
made my way
through it.

Also... beware of callbacks.  I'm not sure if GNAT behaves the same, but
with ObjectAda
if you are inside of a callback from a "C" library and you attempt to
perform an Ada tasking
operation (ie: Rendevous or Protected Operation) bad things happen.
Apparently the
Ada run time library (RTL) keeps additional task control block (TCB)
information for
Ada tasks.
  In these cases I have resorted to using OS primatives for implmented my
own rendevous.

I hope this helps,
SteveD

"Chris" <enderx12@my-deja.com> wrote in message
news:91ondg$lpu$1@nnrp1.deja.com...
> Hi, all... after a long hiatus in the C++ world, I'm finally getting a
> chance to do some more Ada work, at my own suggestion. The ability to
> write production-quality multithread code an order of magnitude faster
> in Ada might have something to do with it.
>
> Anyway, I'm having an irritating problem interfacing with a vendor C
> library. The relevant stuff:
>
>   typedef void* SRV_HANDLE;
>   typedef void* CTX_HANDLE;
>   typedef void* RSLT_HANDLE;
>   typedef void* FLT_HANDLE;
>
>    int GetNextVal(SRV_HANDLE srv, RSLT_HANDLE rslt, CTX_HANDLE *ctx,
>                   char* name, double* dbl, FLT_HANDLE flt);
>
> My take on it in Ada (GNAT 3.13p) is:
>
>    type Srv_Handle is new System.Address;
>    -- same for the other handles
>
>    procedure GetNextVal(Ret  : out int;
>                         Srv  : Srv_Handle;
>                         Rslt : Rslt_Handle;
>                         Ctx  : access Ctx_Handle;
>                         Name : out chars_ptr;
>                         Dbl  : access double;
>                         Flt : Flt_Handle);
>    pragma Import(C, GetNextVal);
>    pragma Import_Valued_Procedure(GetNextVal);
>
> Both Name and Dbl are supposedly set/alloc'd by the library. When I
> call this, it raises Storage_Error on the library call. I am totally
> stumped as to what to fix, or even where to look. Is my Ada declaration
> even remotely correct?
> Other suggestions?
>
>
> Many thanks.
>
> --chris
>
>
> Sent via Deja.com
> http://www.deja.com/





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

* Re: Interface to C; Storage_Error
  2000-12-21  3:25 ` DuckE
@ 2000-12-21 11:38   ` Robert Dewar
  2000-12-23  2:45     ` DuckE
  0 siblings, 1 reply; 11+ messages in thread
From: Robert Dewar @ 2000-12-21 11:38 UTC (permalink / raw)


In article <VKe06.176137$U46.5519033@news1.sttls1.wa.home.com>,
  "DuckE" <nospam_steved94@home.com> wrote:
>   function GetNextVal( srv : access Srv_Handle;
>                        rslt : access Srv_Handle;
>                        ctx  : access Ctx_Handle;
>                        name : C.Char_Array;
>                        dbl  : access C.Double;
>                        flt  : access Flt_Handle ) return
>                                                      C.Int;
>   pragma Import( C, GetNextVal );

A general warning is the reminder that "access foo" is not
a generally usable translation of a pointer parameter in C,
since in the Ada case, null values would not be permitted.

> Since the "C" prototype is using "char *" I suspect you need
> to allocate the data to send to the function.

I see no reason for this suspicion, either on the basis of how
any compiler I know about works, or from the RM, please tell us
where you got this idea from :-)

> Also... beware of callbacks.  I'm not sure if GNAT behaves
> the same, but with ObjectAd if you are inside of a callback
> from a "C" library and you attempt to perform an Ada tasking
> operation (ie: Rendevous or Protected Operation) bad things
> happen.

That sounds like a significant restriction. GNAT has no such
restriction.




Sent via Deja.com
http://www.deja.com/



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

* Re: Interface to C; Storage_Error
  2000-12-20 23:57     ` Chris
@ 2000-12-21 15:35       ` Thomas Wolf
  2000-12-21 18:07         ` Chris
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Wolf @ 2000-12-21 15:35 UTC (permalink / raw)


On Wed, 20 Dec 2000 23:57:28 GMT, Chris <enderx12@my-deja.com> wrote:

>After trying many different configurations,
>I now seem to be making negative progress. So
>I'm going back to the C code and getting my
>brain out of Ada for a few moments... in case
>this helps someone make sense of what I should
>do, here's what the code looks like in C:
>
>  typedef void* SRV_HANDLE;
>  typedef void* RSLT_HANDLE;
>  typedef void* CTX_HANDLE;
>
>
>  SRV_HANDLE hand = 0;
>  RSLT_HANDLE results;
>  CTX_HANDLE ctx = 0;
>  char name[255];
>  double value = 0.0;
>
>  status = InititalizeLibrary("config.txt", &hand);
>  // omitting error checking here
>  status = LookupResults(hand, "keystring", &results);
>  // reset these after every lookup
>  ctx = 0;
>  name[0] = 0;
>  status = GetNextVal(hand, results, &ctx, name, &value);
>  // this call can be repeated to get a series of name/value
>  // pairs. ctx is the handle to keep track of repeated
>  // calls, and starts at the beginning when 0.
>
>Clear as mud? I'm stumped, and sad that my Ada is so rusty.

Try this: (It compiles, but of course I may have misunderstood
something in your C code, or introduced new blunders. Use at
your own risk, and don't blame me for bugs!)

Let me know whether or not it works...

with Interfaces.C.Strings;

package Wrap_C_Code is

  type C_Context is private;

  type C_Error_Code is new Interfaces.C.Int;

  Success : constant C_Error_Code;

  procedure Initialize_Library
    (Ctx    : in out C_Context;
     Name   : in     String;
     Status :    out C_Error_Code);

  procedure Lookup_Results
    (Ctx    : in out C_Context;
     Key    : in     String;
     Status :    out C_Error_Code);

  procedure Get_Next_Value
    (Ctx    : in out C_Context;
     Name   :    out String;
     Last   :    out Natural;
     Value  :    out Interfaces.C.Double;
     Status :    out C_Error_Code);
  --  Raises Constraint_Error if 'Name' is not long enough to hold the
  --  full name returned by the underlying C routine. Otherwise,
  --  Name (Name'First .. Last) contains the name as returned by the C
  --  routine (without a trailing NUL character).

  procedure Reset_Results
    (Ctx : in out C_Context);

private

   Success : constant C_Error_Code := 0; --  I'm guessing...

   subtype SRV_HANDLE  is Interfaces.C.Strings.Chars_Ptr;
   subtype RSLT_HANDLE is Interfaces.C.Strings.Chars_Ptr;
   subtype CTX_HANDLE  is Interfaces.C.Strings.Chars_Ptr;

   type C_Context is
      record
         Server  : SRV_HANDLE  := Interfaces.C.Strings.Null_Ptr;
         Results : RSLT_HANDLE := Interfaces.C.Strings.Null_Ptr;
         Current : CTX_HANDLE  := Interfaces.C.Strings.Null_Ptr;
      end record;

end Wrap_C_Code;

package body Wrap_C_Code is

  procedure Initialize_Library
    (Ctx    : in out C_Context;
     Name   : in     String;
     Status :    out C_Error_Code)
  is
     procedure Init_Lib
       (Status :    out C_Error_Code;
        Name   : in     Interfaces.C.Char_Array;
        Handle : in out SRV_HANDLE);
     pragma Import (C, Init_Lib, "InitializeLibrary");
     pragma Import_Valued_Procedure (Init_Lib);

  begin
     Init_Lib (Status, Interfaces.C.To_C (Name), Ctx.Server);
  end Initialize_Library;

  procedure Lookup_Results
    (Ctx    : in out C_Context;
     Key    : in     String;
     Status :    out C_Error_Code)
  is
     procedure Lookup
       (Status  :    out C_Error_Code;
        Server  : in     SRV_HANDLE;
        Name    : in     Interfaces.C.Char_Array;
        Results : in out RSLT_HANDLE);
     pragma Import (C, Lookup, "LookupResults");
     pragma Import_Valued_Procedure (Lookup);

     use type Interfaces.C.Strings.Chars_Ptr;
  begin
     if Ctx.Results /= Interfaces.C.Strings.Null_Ptr then
        Reset_Results (Ctx);
     end if;
     Lookup (Status, Ctx.Server, Interfaces.C.To_C (Key), 
             Ctx.Results);
  end Lookup_Results;

  procedure Get_Next_Value
    (Ctx    : in out C_Context;
     Name   :    out String;
     Last   :    out Natural;
     Value  :    out Interfaces.C.Double;
     Status :    out C_Error_Code)
  is

     procedure Get_Next
       (Status  :    out C_Error_Code;
        Server  : in     SRV_HANDLE;
        Results : in     RSLT_HANDLE;
        Ctx     : in out CTX_HANDLE;
        Name    : in out Interfaces.C.Char_Array;
        Value   :    out Interfaces.C.Double);
     pragma Import (C, Get_Next, "GetNextVal");
     pragma Import_Valued_Procedure (Get_Next);

     C_String : Interfaces.C.Char_Array (1 .. 255);

  begin
     Get_Next (Status, Ctx.Server, Ctx.Results, Ctx.Current, C_String,
               Value);
     if Status = Success then
        Interfaces.C.To_Ada (C_String, Name, Last);
        --  Last is the number of elements set in 'Name', *not*
        --  necessarily the index of the last element assigned!
        Last := Name'First + Last - 1;
        --  Now it *is* the index of the last element assigned.
     end if;
  end Get_Next_Value;

  procedure Reset_Results
    (Ctx : in out C_Context)
  is
     --  I'm guessing here what "resetting" might be...
  begin
     Interfaces.C.Strings.Free (Ctx.Results);
     Ctx.Current := Interfaces.C.Strings.Null_Ptr;
  end Reset_Results;

end Wrap_C_Code;

-- 
Dr. Thomas Wolf (twolf@acm.org)



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

* Re: Interface to C; Storage_Error
  2000-12-21 15:35       ` Thomas Wolf
@ 2000-12-21 18:07         ` Chris
  0 siblings, 0 replies; 11+ messages in thread
From: Chris @ 2000-12-21 18:07 UTC (permalink / raw)
  To: twolf

In article <3a422218.1843803860@paragate1>,
  twolf@acm.org wrote:
> Try this: (It compiles, but of course I may have misunderstood
> something in your C code, or introduced new blunders. Use at
> your own risk, and don't blame me for bugs!)
>
> Let me know whether or not it works...

Yes, it does!! Thank you incredibly much. A few comments and/or
questions, though...

>   procedure Get_Next_Value
>   --  Raises Constraint_Error if 'Name' is not long enough to hold the
>   --  full name returned by the underlying C routine. Otherwise,
>   --  Name (Name'First .. Last) contains the name as returned by the C
>   --  routine (without a trailing NUL character).

Not an issue; the C library is "guaranteed" to expect a 255-byte array.

>    type C_Context is
>       record
>          Server  : SRV_HANDLE  := Interfaces.C.Strings.Null_Ptr;
>          Results : RSLT_HANDLE := Interfaces.C.Strings.Null_Ptr;
>          Current : CTX_HANDLE  := Interfaces.C.Strings.Null_Ptr;
>       end record;

Is there any particular reason that wrapping these in a context record
would make a difference, as opposed to passing the handles individually
as "in out RSLT_HANDLE", for example? I can see the point of having
them as private types, but it shouldn't affect how they get passed to
C, should it?

>      procedure Lookup
>        (Status  :    out C_Error_Code;
>         Server  : in     SRV_HANDLE;
>         Name    : in     Interfaces.C.Char_Array;
>         Results : in out RSLT_HANDLE);
>      pragma Import (C, Lookup, "LookupResults");
>      pragma Import_Valued_Procedure (Lookup);

Okay... this is the part I *really* want to understand. Why does "in
out RSLT_HANDLE" work and "access RSLT_HANDLE" doesn't? There is
certainly a semantic difference, but isn't access closer to the C
semantics? And how would they be differently implemented by the
compiler (GNAT in this case, but interested in general)?

>      if Status = Success then
>         Interfaces.C.To_Ada (C_String, Name, Last);

This was the only change I really had to make:

          Interfaces.C.To_Ada ( Item => C_String,
                                Target => Name,
                                Count => Last,
                                Trim_Nul => False );

I'm not entirely sure why that matters, but if I think about if for a
bit I'm sure it will make sense. It wasn't raising Terminator_Error
without it, but generally just getting junk.

> Dr. Thomas Wolf (twolf@acm.org)

Again, I am grateful and indebted for the assistance. I just wish I got
to use Ada more often so I keep sharp. (The tragedy is that the client
will probably rewrite it in C++ so it's "easier to maintain".)

--chris


Sent via Deja.com
http://www.deja.com/



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

* Re: Interface to C; Storage_Error
  2000-12-21 11:38   ` Robert Dewar
@ 2000-12-23  2:45     ` DuckE
  0 siblings, 0 replies; 11+ messages in thread
From: DuckE @ 2000-12-23  2:45 UTC (permalink / raw)



>
> > Since the "C" prototype is using "char *" I suspect you need
> > to allocate the data to send to the function.
>
> I see no reason for this suspicion, either on the basis of how
> any compiler I know about works, or from the RM, please tell us
> where you got this idea from :-)
>

In the original post the "C" prototype for the function GetNextVal is:

   int GetNextVal(SRV_HANDLE srv, RSLT_HANDLE rslt, CTX_HANDLE *ctx,
                  char* name, double* dbl, FLT_HANDLE flt);


If I were calling this function inside a C program it would look something
like:

  char name[255];

  dummy = GetNextVal( ..., name , ... );

In this example "name" is allocated by the caller, and the address of that
memory is passed to the function.  I would not expect the called function to
allocate space for "name".  Perhaps you didn't understand what I was
attempting to say the first time?

SteveD






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

end of thread, other threads:[~2000-12-23  2:45 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-12-19 22:28 Interface to C; Storage_Error Chris
2000-12-20  3:52 ` Ted Dennison
2000-12-20  8:55   ` Robert Dewar
2000-12-20 11:39 ` Thomas Wolf
2000-12-20 17:05   ` Chris
2000-12-20 23:57     ` Chris
2000-12-21 15:35       ` Thomas Wolf
2000-12-21 18:07         ` Chris
2000-12-21  3:25 ` DuckE
2000-12-21 11:38   ` Robert Dewar
2000-12-23  2:45     ` DuckE

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