1. 程式人生 > >Qt與vs編寫的dll通訊遇中的坑

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工程