Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Char* and QString



  • I know this is a generic question as it could easily apply to std::string or other char wrapper, but can someone tell me what a good approach is for following scenario. All I can see is the need to copy strings and have the client be responsible for deleting the copies.

    Should I use std::string? I'm reading a lot of articles, api code, stack overflow etc and just can't figure out what a 'good' way of doing this is.

    My hesitance in using std::string is mixed messages from what I’ve read about cross boundary compatibility.
    I.e main() is a seperate process from the shared library A+B are in.
    http://stackoverflow.com/questions/2322095/why-does-this-program-crash-passing-of-stdstring-between-dlls
    http://stackoverflow.com/questions/3167560/passing-stdstring-in-a-library-api

    The key here is ease of use for user as well as maximising performance.

    Scenario:

    I'm implementing an API library.
    The external/public functions (free and class members) use char * for all string operations.
    Internal/private implementation classes use QString.

    @
    // a.h
    Class B;
    Class A
    {
    private:
    B* impl;
    public:
    const char* StringData() const;
    }

    // a.cpp
    const char* A::StringData() const
    {
    QString data = impl->StringData();
    xxxxx <- what should I do here for returning a const char * in a safe way
    }

    // b.h
    class B
    {
    QString m_stringData;
    public:
    const QString StringData() const;
    }

    // b.cpp
    const QString B::StringData() const
    {
    return m_stringData;
    }

    // main.cpp

    int main()
    {
    A a;
    const char *stringData = a.StringData(); <- now have a pointer to array that could be deleted anytime, or user has to delete themselves.

    }
    @



  • There is no generic answer for that. As always, it depends. :-)

    First of all, can you guarantee that the libraries and the main are always compiled with the same compiler? Or at least with 100% compatible ones? I ask this, because on Windows, each MSVS version has it's on c-runtime which use different heaps. This also happens in service packs:

    MSVS2005 != MSVS2005 SP1 != MSVS2008 != MSVS2008 SP1 != MSVS2010

    With != means incompatible c-runtime. So if this could happen, you must be memory neutral in the interface (which you might know from older C-APIs and from som Win32 APIs).

    There a solution could be:

    @
    // a.h
    Class B;
    Class A
    {
    private:
    B* impl;
    public:
    int StringData(char* pData, int nLength) const;
    }

    // a.cpp
    int StringData(char* pData, int nLength) const;
    {
    QString data = impl->StringData();

    QByteArray ba = data.toUtf8();          // this depends on the encoding you need
    int nNeededLength = ba.size() + 1;      // I'm not 100% sure whether the endig 0 is part of the byte array... :-(
    if(0 != pData || nLength >= nNeededLength);
    {
        strcpy(pData, ba.constData());     // this depends on the encoding you need
    }
    return nNeededLength;
    

    }

    // main.cpp
    int main()
    {
    A a;
    char* stringData = 0;
    int nLength = a.StringData(0,0);
    if(0 < nLength)
    {
    stringData = new char[nLength];
    a.StringData(stringData, nLength);
    }
    // ...
    }
    @



  • Thanks for quick answer. I figured out part of the ABI issue is differences between implementations and runtimes etc between compilers and versions.

    I don't like users having to pass in a buffer, it's ugly and makes coding painful. Standard for C users, not expected by C++ users in a modern library.

    Perhaps I need to follow the herd and provide a simple wrapped string class in my API?
    I'll always be returning const data so the wrapper should be pretty simple.

    I've been looking at popular C++ libraries and this seems to be common - I can't see any way around returning copies of strings when crossing module boundaries?


Log in to reply