* 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-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-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-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