Symbian's strings are called descriptors and in most cases are easily converted to Qt strings. Binary data buffers work in a similar way. Both Symbian and Qt have different strengths for character conversion.
Symbian C++ uses descriptors to handle both text and data. Descriptors are self-describing: they use the minimum amount of memory to store the string data and information about its length and memory layout. Descriptors do not resize automatically, and instead panic if an operation goes over the buffer length. This promotes robust code on devices that are designed to be rarely or never rebooted. As mentioned above, they can be used for both text and data because the length is not determined from the presence of NULL ('\0') terminators.
Symbian's descriptor class hierarchy is complicated; providing
concrete modifiable and non-modifiable descriptors that store their
data on the stack or heap, and a number of base classes that are used
for function return types and parameters, but which are not intended
for instantiation (such as TDes
and TDesC
). There are even some pointer descriptors (TPtr
, TPtrC
) which simply point to data stored in other
locations.
Every descriptor class comes in a narrow (8 bit)
and wide (16 bit) variant (such as RBuf8
and RBuf16
, respectively). The 8 bit variant is primarily used
for data, while the 16 bit variant is used for Unicode text. For string
data you actually use the bare version of the descriptors (such as RBuf
) shown in the figure. This is a typedef over the 16
bit variant on all current versions of the Symbian platform.
For detailed information on descriptors, see Descriptors Overview and Using
Descriptors. You should also be aware of TLex
(which is used for lexical parsing and converting numeric strings
into number types), the various typdef classes used for characters: TText
, TChar
, and Charconv for
conversion between character sets. (Charconv converts more sets than
Qt and is extensible.)
Qt uses a single class, QString
for almost all Unicode string handling. The class provides almost
all functionality you might need, including string comparison, conversion
to and from numeric types, and conversion between character sets.
The class integrates with Qt's regular expression classes to provide
powerful parsing and string manipulation. Its also works seamlessly
with Qt's Internationalization APIs.
QString
automatically resizes if necessary to accommodate
a larger string. (If the string cannot be reallocated the operation
throws.) QString uses implicit sharing (copy-on-write) to reduce memory usage and
to avoid the needless copying of data. This means that while the variable
is stored on the stack, the associated data is stored on the heap.
Note: In terms of memory usage, Symbian C++ developers may find it helpful to think of QStrings (and any implicitly shared objects) as reference-counted R-Classes. The object data is allocated on the heap; copy operations that do not change the data simply increase the count without needing to create a new object. The data is only freed when all objects that use it go out of scope.)
The QString
API is much easier to understand than
the descriptor hierarchy, and is more powerful in many respects. QString
is less memory efficient than the descriptor classes,
but still relatively efficient and robust.
Qt also provides QByteArray
(an array of bytes) which can be used for string
operations. QByteArray
is often used for data, and
is discussed in the section Converting Input/output,
binary and geometry data.
Use QString::fromUtf16()
to create a new QString
with a deep copy of the
data at a specified address and length. The address and length are
obtained with TDesC16::Ptr()
and TDesC::Length()
respectively:
QString myString = QString::fromUtf16(theDescriptor.Ptr(), theDescriptor.Length());
Note: qcore_symbian_p.h
defines QString
qt_TDesC2QStringL(const TDesC& aDescriptor)
, which does
this conversion. Because this file is not part of the public API,
you may choose to copy the source code from qcore_symbian_p.cpp
into your own project.
In most cases you can use the
above method to create a copy of the data. If you need to do
a zero copy transfer of data, and you can guarantee that theDescriptor
's lifetime exceeds that of possible Qt variables, you can use QString::fromRawData()
to get a QString
pointing at the Descriptor's data:
QString myString = QString::fromRawData(reinterpret_cast<const QChar*>(theDescriptor.Ptr()),theDescriptor.Length());
8 bit descriptors containing text may be converted to Unicode within Symbian C++ and then transferred as above. This has advantages because Symbian's character conversion classes allow auto-detection of the character set, and provide out-of-the-box support for conversion between more character sets.
However, you may find it easier
to convert them within Qt code. You can use const TUint8*
TDesC8::Ptr() const
to get a pointer to the data in the descriptor.
If you know the character set, you can use QString's fromAscii()
, fromLatin1()
, or fromUtf8()
to
do the conversion. If you just know the data is in the current locale's
default set you can use QString::fromLocal8Bit()
.
Use QString::utf16()
or QString::constData()
to get a pointer to the
data in the QString myString
and cast this to a TPtrC16 (TPtrC)
as shown:
TPtrC myDescriptor (static_cast<const TUint16*>(myString.utf16()), myString.length());
or
TPtrC myDescriptor (reinterpret_cast<const TText*>(myString.constData()),myString.length());
The pointer descriptor is valid while the original QString
(or any shallow copies) are still in scope. Unless you can guarantee
this, you should copy the string into a heap or buffer descriptor.
Using an (RBuf
) heap descriptor do this:
RBuf buffer; qt_symbian_throwIfError(buffer.Create(myDescriptor));
For a buffer descriptor you can do this:
TBuf buffer(myDescriptor);
or:
TBuf<KBufLength> buffer(text.utf16());
The above approach is used in the Dialpad example to copy the
phone number from the QString
into a TBuf
(see implementation of TelephonyPrivate::startCall()
) in Converting active objects to Qt signals and slots.
Note: qcore_symbian_p.h
defines HBufC* qt_QString2HBufC(const QString& aString)
and TPtrC qt_QString2TPtrC( const QString& string )
which
do these conversions. Because this file is not part of the public
API, you may choose to copy the source code from qcore_symbian_p.cpp
into your own project.
Most of the material in this topic is based with permission on a Symbian Foundation wiki article Apps:Using Qt and Symbian C++ Together . The version used was that available at Symbian Foundation on 3 November 2010. The content in this page is licensed under the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License (http://creativecommons.org/licenses/by-sa/2.0/uk).