Just to clarify some points about CStrings which are really confusing...
"Kevin A. Foss" wrote:
Your program is doing exactly what you told it to do You defined a CString which begins byte1 = H, byte 2 = e, etc., disabled error detection with {$X+} and then called it a string: first 4 bytes is capacity, next 4 bytes current length, then the string bytes
[...]
So take out the {$X+} and use functions CString2String and String2CString where you need them.
Yes, this seems to be exactly what I need. Like I said in my original message it was just a case of me misunderstanding how the different string types cooperate -- and I mistakenly thought that straight CString := String assignments worked in a previous gpc version.
GPC does in fact support assignments of Pascal strings to CStrings and handles them correctly (i.e., sets the CString pointer to the beginning of the text in the string, not to the capacity field, and adds a #0 terminator). That was not the problem in your program. The problem was that a local variable is assigned to a CString, and the variable vanishes after the function returns, and a CString is only a pointer and therefore does not contain a *copy* of the text, but only points to the variable which is gone.
This problem will *not* be solved if you use String2CString -- even though it might appear so, since it works a little different internally, the result is still undefined and could be wrong some day. Correct solutions are e.g. GetMem/FreeMem (or New/Dispose), or declaring the local variable static -- in this case it will not vanish, so the CString will remain valid after the function returns, but only until the local variable is changed (i.e., until the function is called again, in general). Something like this is in fact what some libc routines do, and this is considered quite problematic (more difficult to use from a program, not thread-safe, etc.), therefore also my advice: don't use CStrings here. :-)
Is there a guide to all of the different String functions for conversion and what not?
Not yet, I think, but I as far as CStrings are concerned, String2CString and CString2String should be all that's needed (and the former one only rarely, because of the automatic String 2 CString assignments). Also, the block of functions from CStringLength to CopyCString in the GPC unit deals with CStrings.
When calling a routine (of the RTS or of some C library) that expects a CString parameter, don't worry, just pass it a Pascal string :-) -- unless the function will modify the CString, then things get more difficult...
Frank
On Sun, Sep 05, 1999 at 07:35:25AM +0200, Frank Heckenbach wrote:
Just to clarify some points about CStrings which are really confusing...
GPC does in fact support assignments of Pascal strings to CStrings and handles them correctly (i.e., sets the CString pointer to the beginning of the text in the string, not to the capacity field, and adds a #0 terminator).
Well, good that means my memory isn't going.:) The reason why I described the problem with the message subject that I did was because things *did* work correctly if placed in the main program block. Now with the descriptions from Peter and you I realize that I was just lucky before when I had CString working in various function or modules. Perhaps OS/2 just didn't happen to reuse the memory referenced by the pointers as quickly.
Correct solutions are e.g. GetMem/FreeMem (or New/Dispose)
Anyone want to give me a snippet of code?
I assume something like:
Var foo : CString; [...] begin New(foo, 3); { or } GetMem(foo, 3);
To get 3 bytes of string space right? Do I have to worry about enough space for the null, or is that transparent?
When calling a routine (of the RTS or of some C library) that expects a CString parameter, don't worry, just pass it a Pascal string :-) -- unless the function will modify the CString, then things get more difficult...
Okay this is primarilly what I was doing. I've been working on some modules that supply Pascal equivalents of the C socket calls and I was writing my own functions for some routines that were just as easy to rewrite in Pascal (like inet_ntoa() ) and for some reason was being anal and trying to return CStrings like their C equivalents. It makes as much sense to return Pascal strings, to provide a more natural interface on the Pascal side.
Thanks to everyone for their clarifications this week, -Kevin
Kevin A. Foss wrote:
I assume something like:
Var foo : CString; [...] begin New(foo, 3); { or } GetMem(foo, 3);
To get 3 bytes of string space right?
The second.
Do I have to worry about enough space for the null, [...] ?
Yes.
Dealing with `CString's in GPC is like programming in C. `GetMem (foo, 3)' (or - GPC extension - `foo:= GetMem (3)') replaces the `foo = malloc()'. You have to `move' the characters from the Pascal string to the C string because a simple assignment re-assigns the pointer (the CString variable).
Peter