2016-09-26 5 views
2

QtWebEngine은 IPC 메커니즘을 사용하여 C + Qt 월드와 JavaScript 작업간에 통신합니다. 이 메커니즘은 QWebChannel에 사용되며 WebSocket을 기반으로하는 것으로 보입니다. QWebChannel을 사용하지 않고 기본 IPC 또는 WebSocket을 사용하는 방법이 있나요? 후자는 문자열이나 JSON 인코딩 데이터로 제한된 것 같습니다.QWebChannel없이 QtWebEngine의 기본 IPC에 액세스 할 수 있습니까?

배경 : QWebChannel을 사용하여 PTY의 입력/출력을 QtWebEngine에 연결하는 JavaScript 기반 터미널 에뮬레이터 인 QtDomTerm 응용 프로그램을 작성했습니다. 이것은 꽤 잘 작동하지만, utf8/문자열 변환과 관련된 결함이 있습니다. 이상적으로는, 나는 PTY로부터 raw 바이트를 보내고, 자바 스크립트에서 byte-to-text 변환을하고 싶습니다. 그러나 QWebChannel은 너무 높은 수준이며 문자열이나 JSON 인코딩 데이터 만 처리합니다. QByteArray를 처리하지 않습니다.

물론 여러 가지 방법으로 내 문제를 해결할 수 있습니다. 하나는 수동으로 WebSocket 서버를 만들고 QtWebEngine에서 실행중인 JavaScript를 연결하는 것입니다. 그러나 그것은 어쨌든 장면 뒤에서 진행되고있는 것인데, qt.webChannelTransport을 사용하고있는 것처럼 보입니다. 기본 전송 수단 (클래스 WebChannelIPCTransportHost이 관련있는 것으로 보입니다)에 액세스 할 수 있다면 가장 효율적이고 우아 할 것 같습니다.

누구나 다음과 같이 시도했습니다. 나는. 나는 이 아니라 QWebChannel을 사용하고 싶습니다. QByteArray를 전달하는 효율적인 방법이 없다면 말입니다.

은 (명확한 답을 찾지 못하고, 여기에 내가 연구 누락에 대한 코멘트가 발생했습니다. 문제를 고쳐,하지만 난 Qt는 docuemntation, 소스 코드 불구하고 많이 찾아 한합니다.)에서 당신을 방지 무엇

답변

1

QString::fromLatin1(data.toHex())을 보내십시오. dataQByteArray 유형입니까? 그게 당신이 원하는 전부입니다. 자바 스크립트 측면에서 역 변환을 사용합니다 (예 : this question.

+0

:-) 자신을 도울 수 없습니다 (그리고 비교적 간단하게) 바이트를 16 진수로 변환하고 결과 문자열을 전송합니다.그러나 전송되는 데이터의 양이 두 배로 늘어나는 것은 당연히 비효율적입니다. 그것은 또한 나의 감각을 상하게합니다. 왜 바이트를 16 진수로 변환합니까? 우리가 바이트 프로토콜을 사용하는 이유는 무엇입니까? 내 응용 프로그램에서는 QWebChanell의 기능이 필요하지 않습니다. "out-of-band"메시지에 대한 메커니즘이 이미 있으므로 간단한 양방향 바이트 채널 만 있으면됩니다. –

+0

일반 TCP 소켓과 웹 소켓을 사용할 수 없습니까? –

+1

"TCP 소켓과 웹 소켓"을 사용하는 것은 괜찮습니다. 기본적으로 새로운 수신기와 연결을 만드는 대신 기존의 IPC 연결을 피기 백하는 것이 더 간단하고 견고 할 것입니다. QWebChannel은 이미 연결을 설정합니다. 기존 QWebChannel 레벨보다는 낮은 (바이트 스트림) 레벨에서 기존 연결을 사용하는 편이 낫습니다. (질문을 업데이트하여 희망적으로 명확하게 만들었습니다.) –

1

(Qt는 자체가 해킹없이) 세 가지 옵션이있을 듯 QWebChannel "아래"갈 수있는 방법이있을 것 같지 않기 때문에 :

  • 별도의 WebSocket을 연결을 만듭니다. 그러면 더 큰 비 지역 변화가 필요하고, 아마도 추가 공정이 생길 수 있습니다.

  • QTextDecoder를 사용하여 C++ 측에서 바이트 - 텍스트 디코딩을 수행합니다. 그것은 아마도 가장 단순 할 것입니다. 그러나 이스케이프 시퀀스 처리를 수행하는 곳 가까이에서 텍스트 디코딩을 선호하는 아키텍처상의 이유가 있습니다. 그것은 확실히 더 전통적이며 코너 케이스를 더 잘 처리 할 수 ​​있습니다. 플러스 DomTerm은 QtDomTerm 프런트 엔드보다 다른 프런트 엔드와 함께 작동해야합니다.

  • bytestream을 문자열 시퀀스로 인코딩하고 QWebChannel을 사용하여 후자를 전송하고 JavaScript 측에서 바이트로 변환 한 다음 JavaScript에서 텍스트 디코딩을 처리합니다.

세 번째 옵션을 구현하기로 결정했습니다. back-end-forward 변환의 일부 오버 헤드가 있습니다. 그러나, 나는 디자인과 매우 효율적인 인코딩을 구현 :

/** Encode an arbitrary sequence of bytes as an ASCII string. 
* This is used because QWebChannel doesn't have a way to transmit 
* data except as strings or JSON-encoded strings. 
* We restrict the encoding to ASCII (i.e. codes less then 128) 
* to avoid excess bytes if the result is UTF-8-encoded. 
* 
* The encoding optimizes UTF-8 data, with the following byte values: 
* 0-3: 1st byte of a 2-byte sequence encoding an arbitrary 8-bit byte. 
* 4-7: 1st byte of a 2-byte sequence encoding a 2-byte UTF8 Latin-1 character. 
* 8-13: mean the same ASCII control character 
* 14: special case for ESC 
* 15: followed by 2 more bytes encodes a 2-byte UTF8 sequence. 
* bytes 16-31: 1st byte of a 3-byte sequence encoding a 3-byte UTF8 sequence. 
* 32-127: mean the same ASCII printable character 
* The only times we generate extra bytes for a valid UTF8 sequence 
* if for code-points 0-7, 14-26, 28-31, 0x100-0x7ff. 
* A byte that is not part of a valid UTF9 sequence may need 2 bytes. 
* (A character whose encoding is partial, may also need extra bytes.) 
*/ 
static QString encodeAsAscii(const char * buf, int len) 
{ 
    QString str; 
    const unsigned char *ptr = (const unsigned char *) buf; 
    const unsigned char *end = ptr + len; 
    while (ptr < end) { 
     unsigned char ch = *ptr++; 
     if (ch >= 32 || (ch >= 8 && ch <= 13)) { 
      // Characters in the printable ascii range plus "standard C" 
      // control characters are encoded as-is 
      str.append(QChar(ch)); 
     } else if (ch == 27) { 
      // Special case for ESC, encoded as '\016' 
      str.append(QChar(14)); 
     } else if ((ch & 0xD0) == 0xC0 && end - ptr >= 1 
       && (ptr[0] & 0xC0) == 0x80) { 
      // Optimization of 2-byte UTF-8 sequence 
      if ((ch & 0x1C) == 0) { 
       // If Latin-1 encode 110000aa,10bbbbbb as 1aa,0BBBBBBB 
       // where BBBBBBB=48+bbbbbb 
       str.append(4 + QChar(ch & 3)); 
      } else { 
       // Else encode 110aaaaa,10bbbbbb as '\017',00AAAAA,0BBBBBBB 
       // where AAAAAA=48+aaaaa;BBBBBBB=48+bbbbbb 
       str.append(QChar(15)); 
       str.append(QChar(48 + (ch & 0x3F))); 
      } 
      str.append(QChar(48 + (*ptr++ & 0x3F))); 
     } else if ((ch & 0xF0) == 0xE0 && end - ptr >= 2 
       && (ptr[0] & 0xC0) == 0x80 && (ptr[1] & 0xC0) == 0x80) { 
      // Optimization of 3-byte UTF-8 sequence 
      // encode 1110aaaa,10bbbbbb,10cccccc as AAAA,0BBBBBBB,0CCCCCCC 
      // where AAAA=16+aaaa;BBBBBBB=48+bbbbbb;CCCCCCC=48+cccccc 
      str.append(QChar(16 + (ch & 0xF))); 
      str.append(QChar(48 + (*ptr++ & 0x3F))); 
      str.append(QChar(48 + (*ptr++ & 0x3F))); 
     } else { 
      // The fall-back case - use 2 bytes for 1: 
      // encode aabbbbbb as 000000aa,0BBBBBBB, where BBBBBBB=48+bbbbbb 
      str.append(QChar((ch >> 6) & 3)); 
      str.append(QChar(48 + (ch & 0x3F))); 
     } 
    } 
    return str; 
} 

예, 이것은 과잉과 거의 확실 조기 최적화,하지만 난 네, 확실히 행할