I think the solution depends on the type of the characters to be converted, and whether a C-style function with "char *" type arguments needs to be integrated/called.
- If a C-style function needs to be integrated/called, do not use toStdString() followed by c_str(), as the return value type is "const char *" which is not suitable for a C-style function.
- Use toLatin1() followed by data() for ASCII characters.
- Use toLocal8Bit() or toUtf8() followed by data() for other UTF8 characters than ASCII ones.
If several solutions can be used for your specific case, their efficiency levels may be slightly different, which I have not tested.
The following test program shows how to use these solutions:
#include <QCoreApplication>
#include <QDebug>
// This is a C-style test function which needs an argument of type "char *":
void my_c_func(char * my_c_str)
{
printf(" my_c_str[%s]\n", my_c_str);
}
// This is a program which tests the conversion from "QString" to "char *":
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// Case 1: ASCII characters
// ========================
QString qString1 = "French";
qDebug().nospace().noquote() << "qString1[" << qString1 << "]"; // qString1[French]
// Solution 1.1: to Latin1 QByteArray, followed by data() in 2 steps:
QByteArray latin1BAString1 = qString1.toLatin1();
char * latin1_c_str1 = latin1BAString1.data();
qDebug().nospace().noquote() << "latin1_c_str1[" << latin1_c_str1 << "]"; // latin1_c_str1[French]
my_c_func(latin1_c_str1);
// Solution 1.2: to local 8-bit QByteArray, followed by data() in 2 steps:
QByteArray local8bitBAString1 = qString1.toLocal8Bit();
char * local8bit_c_str1 = local8bitBAString1.data();
qDebug().nospace().noquote() << "local8bit_c_str1[" << local8bit_c_str1 << "]"; // local8bit_c_str1[French]
my_c_func(local8bit_c_str1);
// Solution 1.3: to UTF8 QByteArray, followed by data() in 2 steps:
QByteArray utf8BAString1 = qString1.toUtf8();
char * utf8_c_str1 = utf8BAString1.data();
qDebug().nospace().noquote() << "utf8_c_str1[" << utf8_c_str1 << "]"; // utf8_c_str1[French]
my_c_func(utf8_c_str1);
// !!! Try: Solution 1.4: to std::string , followed by c_str() in 2 steps:
std::string stdString1 = qString1.toStdString();
const char * stdstring_c_str1 = stdString1.c_str(); // "const" must be used !
qDebug().nospace().noquote() << "stdstring_c_str1[" << stdstring_c_str1 << "]"; // stdstring_c_str1[French]
// invalid conversion from 'const char*' to 'char*': ---> NOT GOOD for use by a C-style function !!!
// my_c_func(stdstring_c_str1);
qDebug() << "";
// Case 2: Non-ASCII characters
// ============================
QString qString2 = "français";
qDebug().nospace().noquote() << "qString2[" << qString2 << "]"; // qString2[français]
// !!! Try: Solution 2.1: to Latin1 QByteArray, followed by data() in 2 steps:
QByteArray latin1BAString2 = qString2.toLatin1();
char * latin1_c_str2 = latin1BAString2.data();
qDebug().nospace().noquote() << "latin1_c_str2[" << latin1_c_str2 << "]"; // latin1_c_str2[fran?ais] ---> NOT GOOD for non-ASCII characters !!!
my_c_func(latin1_c_str2);
// Solution 2.2: to Local 8-bit QByteArray, followed by data() in 2 steps:
QByteArray local8bitBAString2 = qString2.toLocal8Bit();
char * local8bit_c_str2 = local8bitBAString2.data();
qDebug().nospace().noquote() << "local8bit_c_str2[" << local8bit_c_str2 << "]"; // local8bit_c_str2[français]
my_c_func(local8bit_c_str2);
// Solution 2.3: to UTF8 QByteArray, followed by data() in 2 steps:
QByteArray utf8BAString2 = qString2.toUtf8();
char * utf8_c_str2 = utf8BAString2.data();
qDebug().nospace().noquote() << "utf8_c_str2[" << utf8_c_str2 << "]"; // utf8_c_str2[français]
my_c_func(utf8_c_str2);
// !!! Try: Solution 2.4: to std::string, followed by c_str() in 2 steps:
std::string stdString2 = qString2.toStdString();
const char * stdstring_c_str2 = stdString2.c_str(); // "const" must be used !
qDebug().nospace().noquote() << "stdstring_c_str2[" << stdstring_c_str2 << "]"; // stdstring_c_str2[français]
// invalid conversion from 'const char*' to 'char*': ---> NOT GOOD for use by a C-style function !!!
// my_c_func(stdstring_c_str2);
return a.exec();
}
The above code has been tested using Qt 5.4 for Linux.
A second subject involved in this question is whether we can chain functions together during this 2-step conversion process:
<myQString>.to<AnotherClass>().<getCPointer>(); // OK or not?
I think this depends on "AnotherClass" and on the type of characters to be converted. Based on some documentation on QString, QByteArray and std::string, it appears that it is safe to write:
<myQString>.toStdString().c_str(); // OK.
<myQString>.toUtf8().data(); // Should be OK as QString is Unicode string.
But the following lines should be avoided:
<myQString>.toLocal8Bit().data(); // May crash if the converted QByteArray object is undefined !
<myQString>.toLatin1().data(); // May crash if the converted QByteArray object is undefined !