Classification: |
C++ |
Category: |
Base |
Created: |
06/20/97 |
Modified: |
07/22/2003 |
Number: |
FAQ-0599 |
Platform: |
Not Applicable |
|
Question: I'm a programmer used to other C++ environments. Please could I have a crib sheet to help me use descriptors?
Answer: Here are some guidelines and examples for translating from C or C++ in other environments to the Symbian OS environment. · Replace char* data members, variables and function return values with TPtr, TPtrC or HBufC* · Replace char* parameters to functions with (const TDesC&) or (TDes&) · Replace char[N] data members and variables with TBuf or TBufC · Replace const char* with the 'C' versions of the classes · For allocated memory use HBufC*. · Use the constructor or Set() to change what a descriptor points to; use the assignment operator to change what its buffer
contains. · Warning: Initialisation and assignment have totally different semantics. This contravenes almost every C++ style guide in existence, but the decision dates back to before most
of them existed and now we're stuck with it. The assignment operator does a memory copy. In the following examples, string represents a read-only character string. buf represents a modifiable buffer for manipulating strings.Data Members and Initialization
Typical C++ For Null-Terminated Strings |
In Psion EPOC32 |
char buf[BUFSIZE]; |
TDes buf; |
// String referenced by a class: const char* iString;
iString = ...;
|
TPtrC iString; iString.Set( ... );
|
// String managed by a class char * iBuf = ... ;
|
HBufC* ipBuf = ... ; |
const char* string = "Hello"; |
TPtrC string( _L( "Hello" ) ); |
const char* string = charArrayZ; |
TPtrC string( charArrayZ ); |
Parameters and values
foo( const char* aString ) |
foo( const TDesC& aString ) |
modify( char * aBuf, int iSize ); |
modify( TDes& aBuf ); |
// Returning allocated memory char* buf = foo()
delete [] buf;
|
HBufC* pBuf = foo() delete pBuf;
|
// Returning ptr to another's mem const char* string = foo();
|
TPtrC string = foo(); |
Operations on strings
strlen( string ); |
string.Length(); |
memset( buf, '\0', BUFSIZE ); |
buf.FillZ( buf.MaxLength() ); |
buf[0] = '\0'; |
buf.Zero(); |
strcpy( buf, "Hello" ); |
buf = _L( "Hello" ); |
sprintf( buf, "%s\n", string ); |
buf.Format( _L("%S\n"), &string); |
strcpy( buf, string1 ); strcat( buf, string2 );
|
buf = string1; buf.Append( string2 );
|
char * iBuf = strdup( string ); |
HBufC* ipBuf = string.AllocL(); |
Notes
Descriptors reference chunks of memory of known size. Compared with standard C they replace the common combination of char*
plus integer buffer length.
Descriptors combine The data adress [ char* x; ]
The data length [ strlen( x ) ], and, for modifiable buffers:
The buffer size [int xBufferSize; ]
They cope seamlessly with unicode (two-byte) characters.
What the classes actually contain:
TDesC (abstract base class for everything) has a length;
TPtrC adds a memory address to TDesC.
TDes (abstract) is a modifiable TDesC, and therefore adds a maximum length to TDesC
TPtr adds a memory address to TDes
TBufC contains a read-only char array of size N
TBuf contains a read-write char array of max size N, plus its current length
HBufC adds an allocated buffer to TDes. The 'C' is misleading; an HBufC is modifiable; just call Des() on it to get a TPtr.
You might think of it as similar to a Pascal string, combining length and allocated memory. Use HBufC::New(), NewL() or NewLC()
to allocate an empty buffer, or use the function AllocL() on any descriptor to make an allocated copy of its data.
|