Qt與vs編寫的dll通訊遇中的坑
一、前言:
因為實際開發過程中遇到Qt呼叫vs編寫的sdk,故用vs封裝成純C++的dll提供Qt使用,因為懶得遷移整個工程到Qt環境,畢竟沒學過Qt,光是搭建環境,怎麼使用creator就很多時間折騰了,時間成本很高。
二、新建vs的dll
1、生成dll、lib
2、新建Qt工程,把包含標頭檔案
3、配置lib
4、dll放到exe目錄下
5、編寫客戶端daim
int main(int argc, char *argv[]) { TreeBuilder builder; builder.test01(); std::string tt=builder.getString(temp); qDebug()<<tt.c_str()<<endl; }
6、執行看效果
三、原因分析和解決方法
1、原因是,字符集編碼不一樣,導致同一塊記憶體兩種含義,詳細請看上一節講解:https://blog.csdn.net/LittleLittleFish_xyg/article/details/83896107
2、如何解決呢?
既然c++的string有這個陷阱,解決方法為換一種傳入的引數,改為unsigned char *,內部再使用unsigned char *到string的轉換(注意用char,跨平臺還可能是陷阱)
請仔細檢視修改後的實現
3、客戶端程式碼
int main(int argc, char *argv[]) { unsigned char str_temp[]="world"; TreeBuilder builder; builder.test01(); unsigned char* tt=builder.getString(str_temp); char *buf = reinterpret_cast<char*>(tt); qDebug()<<"return:"<<buf<<endl; }
4、執行結果:
四、new物件產生的坑(遺留的bug,還沒有找到解決方法)
描述:dll中使用了new操作符,並在dll中使用該指標,vs工廠呼叫dll能正常使用dll中的指標,但是Qt呼叫vs的dll不正常,於是將vs的dll和Qt程序聯調進入dll的執行程式碼中發現,new出來並賦值後的記憶體全部為空,導致不可收拾的災難。
個人理解:dll中的new實際上是exe的程序地址空間(這方面的知識可以在window核心程式設計的資料中看到),即vs工程exe呼叫dll時,dll中new出來的地址,是vs工程的程序地址,而Qt呼叫dll時是qt程序的地址,由於兩種程序地址存在差異導致記憶體不能正常讀取,Qt編碼UTF-8,vs的是Unicode。當vs編譯dll時候,認為你用Unicode的方式找到這個記憶體,而qt呼叫的dll的時候,卻根據utf-8的記憶體來讀寫,dll中new出來的地址A,在qt程序確是對應B的地址位置,這時候還檢視A地址,當然是有問題的(對邏輯地址的理解還不夠,不知道是否正確,僅供參考)
如有大神指導一下這個bug的解決方法,實在感激不盡!因為這個bug的緣故,導致我放棄VS寫這個sdk,改用Qt。
五、總結
跨平臺一定要謹慎,能不誇儘量不跨,當然高手另當別說,對於新手各種細節不理解,出現各種問題不知如何尋求答案,經常一個小問題導致好幾天沒有進度。本來是想解救一下bug,卻發現還留了一個坑,最後還是走了遷移程式碼的路!
下一節介紹Qt工程如何聯調vs的dll工程