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
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.