January 8, 2008

Handbook Note 74/113: PChar to String

Note 74 of 113 of Delphi 2007 Handbook

Note 74: In the sample code for the SHGetFolderPath function, after the call I've reset the string length by re-casting it to PChar. This apparently useless line of code causes Delphi to reset the “Pascal string length” from the “C string length”, so that if you append another string to it you'll get the expected result. Do this operation every time you pass a string buffer to a Windows API function for it to be written.

This blog post is part of my "113 Delphi 2007 Handbook Notes" blogging project, to promote my new Delphi book.





 

5 Comments

Handbook Note 74/113 PChar to String 

I don't understand this note without seeing the code
it's referring to.  Would you be able to post that
line of code (or a similar one) please?

I think the source of my confusion is that I thought
the string type could handle appending a C-string and
the final resulting (native Delphi) string would have
the correct length.  So... how or why would this not
be the case?  Is this passing a string into an API
call to be /written to/, not read from, maybe?
Comment by David M [] on January 9, 03:21

Handbook Note 74/113 PChar to String 

David,

  good point... and yes, this is a case in which you
pass a PChar to a Windows API for writing, not
reading. This is the original code snippet the note
comments on:

var
  szBuffer: string;
begin
  SetLength (szBuffer, 250);
  SHGetFolderPath (Handle, CSIDL_PERSONAL,
    TOKEN_DEFAULTUSER, 0, PChar(szBuffer));
  szBuffer := PChar(szBuffer);
Comment by Marco Cantù [http://www.marcocantu.com] on January 9, 10:36

Handbook Note 74/113 PChar to String 

I'd use

SetLength (Buffer, MAX_PATH);

To ensure the buffer is sized up to the max path size 
used by the version of Windows the application is 
running on - and try to avoid buffer overflows.
 
Comment by Luigi D. Sandon on January 9, 13:43

Handbook Note 74/113 PChar to String 

Thanks Marco!  I didn't actually realise you could do
that - I've always passed in 'genuine' PChars, ie as
pointers to my own character buffer and created a
string from that after the function writing to it is
called.  Guess you learn something every day :)
Comment by David M on January 10, 01:05

Handbook Note 74/113 PChar to String 

 Even better is this :

procedure Example_WINAPI_returns_length;
var
  s: string;
begin
  // First, call the API without a buffer, to get the 
length) :
  SetLength(s, WINAPI({buffer=}nil, {length=}0));
  // Now, test if the call is needed anyway :
  if Length(s) > 0 then
    // Call it with the supplied buffer, and update 
the string-length for good measure :
    SetLength(s, WINAPI({buffer=}@(s[1]), {length=}
Length(s)));
end;
Comment by Patrick van Logchem [http://www.every-angle.com] on January 10, 22:35


Post Your Comment

Click here for posting your feedback to this blog.

There are currently 0 pending (unapproved) messages.