PDA

View Full Version : wchar_t vs QString support with QT IPC server and Windows Natice IPC Client



nbkhwjm
3rd May 2013, 18:41
all i have a QT app that opens a IPC port on windows and waits for a connection from a client... when i connect with QT client its fine, however a native windows app, it fails to get the proper data. I am convinced its a character encoding issue. But im unsure as to the *best* way to address it... i can alter either the QT app or the Native windows app..This will only run on windows, so portability isnt a concern. The Client MUST be native windows, so i cant do all QT... (i wish believe me)

I see the count of the data received in the client as "READ(30)", so i know data is going...

QT IPC Socket Code

void LocalSocketIpcServer::returnPrinter(QString printer)
{

PRN_DEBUG() << "Returning: " << printer;

QByteArray block;
QDataStream out(&block, QIODevice::ReadWrite);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << printer;
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

QLocalSocket *clientConnection = m_server->nextPendingConnection();

connect(clientConnection, SIGNAL(disconnected()),
clientConnection, SLOT(deleteLater()));

clientConnection->write(block);
clientConnection->flush();
clientConnection->disconnectFromServer();

emit finishedSending();
}


Native Windows client

#include <windows.h>
#include <conio.h>
#include <iostream>
using namespace std;

const wchar_t cszPipeName[] = L"\\\\.\\pipe\\TestPort";

int main(int argc, wchar_t* argv[])
{
HANDLE hPipe = INVALID_HANDLE_VALUE;

do {

// Get handle to a read only pipe that must exists.
hPipe = CreateFileW(
cszPipeName,
GENERIC_READ, // | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);

if( hPipe == INVALID_HANDLE_VALUE ){
cerr << "CreateFile fail. Err: " << GetLastError() << endl;
break;
}

cout << "Press any key to exit" << endl;

wchar_t szMessage[256] = {0};

// Keep buffer null terminated. Don't use last element.
DWORD dwMsgSize = (sizeof(szMessage)-1)*sizeof(wchar_t);

//while(!_kbhit()) {

// Read messages until an error on the pipe happen
// or the user press any key on the keyboard.
DWORD dwRead = 0;
BOOL bRet = ReadFile(
hPipe,
szMessage,
dwMsgSize,
&dwRead,
NULL
);
if(!bRet) {

cerr << "Read fail. Err: " << GetLastError() << endl;
break;
}

wcout << "READ (" << dwRead << ") " << szMessage << endl;

//} // end while

} while(false); // end do

if(hPipe != INVALID_HANDLE_VALUE) {
CloseHandle(hPipe);
}

return 0;
}

ChrisW67
4th May 2013, 03:07
QDataStream is a Qt serialisation mechanism. For all but the intrinsic types it writes more to the stream than you expect in order that the receiving Qt program can reconstruct the objects by reading from QDataStream. This is certainly the case with QString, which will output a 4 byte length followed by the internal data representing the string (probably a 16-bit ints). Your generic receiver does not account for this.

If you are sending to a non-Qt receiver then you best avoid QDataStream and use QIODevice::write() directly.