2016-09-26 140 views
2

QtWebEngine使用IPC機制在C + Qt世界和JavaScript工作之間進行通信。這種機制用於QWebChannel,它似乎基於WebSockets。有沒有辦法在不使用QWebChannel的情況下使用底層IPC或WebSockets,因爲後者似乎僅限於字符串或JSON編碼數據?我可以在沒有QWebChannel的情況下訪問QtWebEngine的底層IPC嗎?

背景:我編寫了一個應用程序QtDomTerm,它是一個基於JavaScript的終端仿真程序,它使用QWebChannel將PTY的輸入/輸出連接到QtWebEngine。這工作相當好,但有一個與utf8 /字符串轉換有關的故障。理想情況下,我想從PTY發送原始字節,並在JavaScript中進行字節到文本的轉換。但QWebChannel太高級,只能處理字符串或JSON編碼的數據。它不處理QByteArray。

當然有多種方法可以解決我的問題。一種是手動創建一個WebSocket服務器,並讓QtWebEngine中運行的JavaScript連接到它。但似乎無論如何都是這樣,使用qt.webChannelTransport。看起來如果我可以訪問底層的交通工具(類似WebChannelIPCTransportHost似乎是相關的),它會是最高效和優雅的。

任何人都試過這樣的事情?即我想不是使用QWebChannel - 除非有一種有效的方式來傳遞QByteArray。

(我改寫的問題。有失蹤的研究評論,但我已經很大程度上瀏覽儘管Qt的docuemntation,源代碼,在這裏,沒有找到一個明確的答案。)

回答

1

什麼阻止你發送QString::fromLatin1(data.toHex()),其中dataQByteArray類型?這就是你需要的,真的。在javascript一側使用反向轉換,請參閱this question

+0

是的,這是肯定是可行的(並且相對簡單)將字節轉換爲十六進制,並傳輸結果字符串。但它無可否認效率低下,因爲它將傳輸的數據量加倍。它也冒犯了我的優雅感:爲什麼要將字節轉換爲十六進制 - 無論如何,當我們使用字節協議時。在我的應用程序中,我確實不需要QWebChanell的功能 - 我只需要一個簡單的雙向字節通道,因爲我已經有了一種「帶外」消息機制。 –

+0

你不能使用普通的TCP套接字和websockets嗎? –

+1

使用「TCP套接字和websockets」很好(實質上是我想做的) - 但不是創建一個新的監聽器和連接,我認爲在現有的IPC連接上更簡單,更強大。 (例如,並非所有環境都可以訪問TCP套接字。)QWebChannel已經建立了一個連接;我只想在低(字節流)級別使用現有連接,而不是較高的QWebChannel級別。 (我更新了這個問題,希望更清楚一點。) –

1

因爲似乎沒有要很長的路要走「下面」的QWebChannel(沒有黑客的Qt本身)似乎有三種選擇:

  • 創建一個單獨的WebSockets連接。這需要更大的非本地更改,並可能會創建額外的流程。

  • 在C++端執行字節到文本解碼,也許使用QTextDecoder。這可能是最簡單的。但是,有一些體系結構的原因讓我們更喜歡在接近我們做轉義序列處理的地方進行文本解碼。這當然更傳統,並可能更好地處理角落案件。另外DomTerm需要與QtDomTerm前端的其他前端一起工作。

  • 將字節流編碼爲一串字符串,使用QWebChannel傳輸後者,在JavaScript端轉換回字節,然後在JavaScript中處理文本解碼。

我選擇實施第三個選項。在轉換後端的方面有一些開銷。不過,我設計和實現的編碼是相當有效率:

/** 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; 
} 

是的,這是矯枉過正,幾乎可以肯定過早的優化,但我不能幫助自己:-)

相關問題