環境:
Ubuntu18.04
開發板:debian
交叉編譯工具鏈:arm-linux-gnueabihf-gcc 8.3.0
Qt:Qt5.11.2
解決方案在文末,如不想看中間過程,可直接跳轉到文末。
mqtt是一種工業物聯網協議,可以用來連接阿里雲、百度雲、onenet等雲端,應用廣泛。
關於mqtt的使用,網上資料主要有以下幾種:
1、STM32+ESP8266:這種方式主要是藉助ESP8266模塊來聯網,至於mqtt協議基本上是要自己實現的。也就是mqtt的報文需要自己去構建,好在mqtt的報文並不是很複雜,稍微研究一下也能理解。
2、Linux下使用官方sdk包,比如阿里雲有提供阿里的sdk包,下載後調用它提供的接口來連接阿里雲。
3、QT裡移植mqtt:這種方式因為可以直接調用官方寫好的接口,因此使用起來就簡單多了,但是這個移植過程並不是那麼簡單。這分為Windows端和Linux端。Windows端就不說了,我主要說一下Ubuntu下和arm開發板上的移植。
移植也分為兩種,一種是編譯成動態連結庫,一種是直接把mqtt官方源碼包含進去自己的工程裡面,然後一起編譯。我本人覺得要編譯成庫,然後配置環境變量什麼的比較麻煩,還不如直接把源碼包含進去。
先說Ubuntu下的移植:
這個我是參考網上的,[Linux Qt下MQTT模塊的導入(移植)](https://blog.csdn.net/wct3344142/article/details/107022706/)
按照這篇博客來操作,實測有效,總結起來非常簡單,就是下載源碼,添加到自己的工程中,然後編譯,編譯出錯的都是因為頭文件包含的時候,應該把<>替換成"",這兩種頭文件包含的區別相信大家都很清楚。
這樣就移植好了。可以看到,在這裡使用gcc編譯可以通過,並且寫個簡單的測試代碼,確實能連接雲端
接下來說一下移植到arm端:
這部分網上的資料是真的少,搜索半天都找不到你想要的。
我們知道,要移植到arm開發板上面,需要使用交叉編譯工具鏈,正常情況下,你寫好的qt程序在主機Ubuntu上能運行,只要換成交叉編譯工具編譯,就可以放到開發板上運行了。
但是這裡你這樣做會發現報錯。
提示QSslConfiguration這種類型不認識(未定義)。於是我就去找一下這個在哪裡有定義,找了一下,發現這種類型其實在qsslconfiguration.h這個文件中是有定義的,但是前面通過#ifndef QT_NO_SSL這個宏沒有把這段代碼編譯進去
於是真相大白了,在gcc裡沒有那個宏定義,所以下面那段代碼會被編譯,所以自然就不會出現未定義這種錯誤。但是當使用交叉編譯工具鏈的時候,在qtnetwork-config.h這個文件中找到了這個宏定義,所以#ifndef QT_NO_SSL 到#endif之間的代碼都不會被編譯,自然QSslConfiguration就會未定義了。
於是我猜想,把qtnetwork-config.h中的這個QT_NO_SSL宏給注釋掉,應該就可以了,雖然 說這樣亂改代碼可能導致一些意想不到的結果,但我還是想試一下看能不能編譯通過。結果發現會出現一連串的連鎖反應,改了這個,又會出現新的錯誤,所以這種方法不行。而且像這種文件它默認是只讀的,也就是說它本來就不希望你去修改,所以不應該這樣做。
後面我又想,既然直接改變宏定義不行,能不能把報錯的地方直接注釋掉,反正那些函數可能並沒有用到,所以注釋掉應該不會有什麼影響
這裡是報錯的那個類的頭文件,再切換到源文件
發現都是沒有編譯的,但是仔細觀察源文件,其實也是有QT_NO_SSL這個宏的
這裡就讓人覺得很奇怪了,同樣是有這個宏,其他的地方都不會被編譯,這裡卻會被編譯,而且其他地方都可以跳轉到qtnetwork-config.h文件中去,這裡卻不會。
那麼,很容易猜到,在這個源文件裡沒有包含qtnetwork-config.h這個頭文件,導致沒有定義那個宏。
解決辦法:在qmqtt_ssl_socket_p.h文件中添加一句代碼:
#include "qtnetwork-config.h"
問題成功解決。把編譯好的文件放在arm開發板上,可以成功執行
至此,移植結束,可以盡情開發了。
後臺回復mqtt獲取我修改後的mqtt源碼包