2012-01-28 2 views
1

두 개의 기본 모듈로 구성된 응용 프로그램이 있습니다. 하나는 C로 작성되었고, 표준 C 런타임 라이브러리와 Qt C++로 작성된 라이브러리를 사용합니다. 그들은 IPC와 서로 통신합니다. C 모듈은 char 배열을 만들고, 그것을 데이터로 채우고 Qt로 작성된 모듈로 보냅니다. QDataStream을 사용하여 수신 된 데이터를 deserialize하고 싶지만, 내 노력으로 아직 결과가 나오지 않았다. 당신이 볼 수 있듯이QDataStream은 맞춤 제작 된 문자 배열과 작동하지 않습니다.

unsigned int pointer = 0; 
const int IPC_MSG_LEN = 500; 
const int IPC_MSG_HEADER = 200; 
const int SOMETHING = 1443; 
char api = 55; 

char msg[IPC_MSG_LEN] = {0}; 
memcpy_s(msg, IPC_MSG_LEN, &IPC_MSG_HEADER, sizeof(int)); 
pointer = sizeof(unsigned int); 
memcpy_s(&msg[pointer], IPC_MSG_LEN - pointer, &api, sizeof(char)); 
++pointer; 
memcpy_s(&msg[pointer], IPC_MSG_LEN - pointer, &SOMETHING, sizeof(int)); 

QByteArray arr(msg, IPC_MSG_LEN); 
QDataStream ds(&arr, QIODevice::ReadOnly); 
qint32 header = 0, aa = 0; 
qint8 t_api = 0; 
ds >> header; //Doesn't work 
ds >> t_api; //Works 
ds >> aa; //Doesn't work 

이 코드는 매우 간단하지만, 헤더와 AA 변수는 임의의 숫자로 직렬화 복원됩니다 여기에 내가 달성하기 위해 노력하고있어 간단한 예입니다. 그러나 t_api (1 바이트 변수)에는 올바른 값이 할당되어 있습니다. 이 코드의 문제점은 무엇입니까? QDataStream은 사용중인 개인 데이터 형식과 호환되지 않는 개인 데이터 형식을 사용합니까? 내 자신의 QIODevice 구현을 작성해야합니까 아니면 제가 인식하지 못하는 빠른 수정이 있습니까? :) 감사합니다. 도움을 주셔서 감사합니다.


업데이트는 솔루션이 그 기본 데이터 형과 함께 완벽하게 작동, 당신이 아주 많이들 감사하지만, 문제는 내가도 너무 * 문자열을/역 직렬화 문자를 직렬화 할 수 있어야한다는 것입니다.

wchar_t* name1 = L"something"; 
memcpy_s(&msg[pointer], IPC_MSG_LEN - pointer, name1, (wcslen(name1) + 1) * 2); 

char* ai = new char[500]; 
ds >> ai; //ai becomes NULL here :| 

달성 할 수있는 방법이 있습니까? 다시 한 번 감사드립니다

답변

3
QDataStream::setByteOrder(QDataStream::LittleEndian); 

#include <QDebug> 
#include <QByteArray> 
#include <QDataStream> 
#include <QString> 
#include <vector> 

template<typename T> void writePtr(char*&dst, T data){ 
    *reinterpret_cast<T*>(dst) = data; 
    dst += sizeof(T); 
} 

int main(int argc, char** argv){ 
    const size_t ipcSize = 512; 
    std::vector<char> buffer(ipcSize, 0); 
    quint32 sendVal1 = 0x12345678, recvVal1 = 0; 
    quint8 sendVal2 = 0xee, recvVal2 = 0; 
    quint32 sendVal3 = 0x9999abcd, recvVal3 = 0; 
    char* dst = &buffer[0]; 
    writePtr(dst, sendVal1); 
    writePtr(dst, sendVal2); 
    writePtr(dst, sendVal3); 

    QByteArray byteArray(&buffer[0]); 
    QDataStream stream(&byteArray, QIODevice::ReadOnly); 
    stream.setByteOrder(QDataStream::LittleEndian); 

    stream >> recvVal1 >> recvVal2 >> recvVal3; 

    qDebug() << QString(QObject::tr("sent: %1, received: %2")).arg(sendVal1, 8, 16).arg (recvVal1, 8, 16); 
    qDebug() << QString(QObject::tr("sent: %1, received: %2")).arg(sendVal2, 2, 16).arg(recvVal2, 2, 16); 
    qDebug() << QString(QObject::tr("sent: %1, received: %2")).arg(sendVal3, 8, 16).arg(recvVal3, 8, 16); 

    return 0; 
} 

는하지만 문제는 내가도 너무 * 문자열을/역 직렬화 문자를 직렬화 할 수 있어야한다는 것입니다.

Qt 데이터 직렬화 형식에 대해 자세히 설명합니다 (here). IPC 용 QDataStream을 사용하려면에 해당 문서를 읽어야합니다. Qt는 멋진 documentation을 가지고 있으므로 사용하십시오.

wchar_t* name1 = L"something"; 

그것은 wchar_t* 문자열은 다음과 같습니다

또한이 숯불 * 문자열이 아닙니다.

wchar_t은 컴파일러에 따라 크기가 다릅니다 (wchar_t 당 4 또는 2 바이트). 이는 IPC의 문제를 의미합니다. wchar_t과 달리 char은 1 바이트 크기로 보장됩니다. 그래서 하나가 UTF8로 전체 문자열을 인코딩 (또는 알려진 코드 페이지/인코딩 8 비트 인코딩 된 문자열을 사용) QByteArray-compatible format에 원시 데이터로 쓰기 :

void writeDataPtr(char*& ptr, const char* data, quint32 size){ 
    if (!data){ 
     size = 0xffffffff; 
     writePtr(ptr, size); 
     return; 
    } 

    memcpy(ptr, data, size); 
    ptr += size; 
} 

을 그 다음 (또는 QTextCodec를 디코딩 QString::fromUtf8를 사용 - 당신이 결정하는 경우 utf8 대신 다른 8 비트 인코딩 사용). 또는 인 경우 wchar_t* 문자열이 UTF16 규격 sizeof(wchar_t) == 2인지 확인하고 QString-compatible format에 덤프 할 수 있습니다.

그건 그렇고 - 내가 너라면, memcpy_s을 피할 것입니다. C++ 표준의 일부가 아니기 때문에이를 피할 수있는 좋은 이유가됩니다. 내가 원하는


스트림의 위치가 문자를 종료 null로 때까지 QDataStream에서 */숯불 *를 wchar_t를 읽는 것입니다.

숙제 인 경우 그에 따라 게시물에 태그를 답니다. 그 중

하나는 작동합니다 :

QString readWcharString(QDataStream& stream){ 
    QVector<ushort> rawData; 
    ushort tmp; 
    do{ 
     stream >> tmp; 
     rawData.push_back(tmp) 
    }while(tmp); 
    return QString::fromUtf16(rawData.data()); 
} 

또는

QString readWcharString(QDataStream& stream){ 
    QVector<wchar_t> rawData; 
    ushort tmp; 
    do{ 
     stream >> tmp; 
     rawData.push_back(tmp) 
    }while(tmp); 
    return QString::fromWCharArray(rawData.data()); 
} 
+0

안녕하세요. 지원해 주셔서 감사합니다. 내 업데이트 된 게시물을 한번보세요. – Davita

+0

감사합니다. 그러나 귀하의 답변이 내 상황에서 어떻게 도움이되는지 이해하지 못합니다. wchar_t와 char의 차이점을 알고 있습니다. 스트림 위치가 null 문자를 종료 할 때까지 QDataStream에서 wchar_t */char *를 읽는 것이 좋습니다. 그러나 이것이 QDataStream의 기본 동작이 아니라고 생각합니까? – Davita

+0

@Davita : "보낸 사람"을 수정하여 QDataStream 호환 형식으로 데이터를 덤프하거나 수신기를 수정하여 QDataStream을 사용하여 "비표준"데이터를 읽습니다. >>로 QDataStream에서 wchar_t 문자를 읽는 것은 == 0 인 문자가 "숙제"난이도를 가지며 5 행의 코드가있는 하나의 서브 루틴을 추가하는 문제입니다. 그렇다면 문제는 어디에 있습니까? – SigTerm

3

QDataStream은 기본적으로 빅 엔디안 형식으로 숫자를 저장합니다.
당신이 있음을 변경할 수 있습니다

ds.setByteOrder(QDataStream::ByteOrder(QSysInfo::ByteOrder)); 

대신 감지 호스트 엔디 언을 사용하는 것이다.

+0

안녕, 귀하의 지원을 주셔서 감사합니다. 내 업데이트 된 게시물을 한번보세요. – Davita

관련 문제