行唐縣做網(wǎng)站電話李勇seo的博客
閑談
因為Qt封裝了很多個人感覺很好用的庫,所以一直想通過CAPL去調(diào)用Qt實現(xiàn)一些功能,但是一直沒機會(網(wǎng)絡上也沒看到這方面的教程),這次自己用了兩天,踩了很多坑,終于是做成了一個初步的調(diào)用方案,雖然有點麻煩,但是以后可能會讓自己提高很多的效率。
之前的方案是通過Qt制作面板,然后CAPL和Qt通過tcp/udp進行通訊,實現(xiàn)了部分功能
現(xiàn)在是直接封裝成dll,不需要單獨打開Qt程序的界面
廢話結束,進入正題
制作Qt的DLL
可以參考這個博主的博客
https://www.cnblogs.com/susiesnai-sun/p/16872488.html
我的dll是解析HEX,BIN,S19文件的,雖然這個可以capl解決,但是為了復用,還是做了一個
如下圖
.pro
.h
.cpp
因為涉及公司相關的東西,.CPP不全,只當作參考,但是過程很明顯
制作capl dll
打開CANoe給定的制作dll的demo,下附制作的代碼,可以參考。在這里遇到一些問題,生成的dll在CANoe調(diào)用的時候,總是加載庫函數(shù)失敗,通過自己新建c++項目發(fā)現(xiàn),因為是dll調(diào)用dll,我猜是因為項目的路徑有問題,然后把對應的dll全部放到項目路徑下才加載成功。切記。
HANDLE hThead;
uint16_t File_flag = 0;
char fileName[10000] = "";
typedef uint8_t(*BOOTFILERED)(char[], uint8_t*, uint64_t&); // 定義函數(shù)指針類型
HMODULE hLib = NULL;
uint8_t fileData[10000000];
uint64_t fileDataLength = 0;DWORD _stdcall readFileThread(LPVOID p)
{if (File_flag == 1){BOOTFILERED readS19;// 導出函數(shù)地址readS19 = (BOOTFILERED)GetProcAddress(hLib, "readS19");readS19(fileName, fileData, fileDataLength);}else if (File_flag == 2){BOOTFILERED readHex;// 導出函數(shù)地址readHex = (BOOTFILERED)GetProcAddress(hLib, "readHex");readHex(fileName, fileData, fileDataLength);}else if (File_flag == 2){BOOTFILERED readBin;// 導出函數(shù)地址readBin = (BOOTFILERED)GetProcAddress(hLib, "readBin");readBin(fileName, fileData, fileDataLength);}else {return 4;}return 0;
}uint64_t CAPLEXPORT CAPLPASCAL readFile(char file[], uint16_t flag)
{if (hLib == NULL)//檢測是否加載dll成功{hLib = LoadLibrary("bootloadReadFile.dll");if (hLib == NULL)//檢測是否加載dll成功{printf("加載DLLTest1.dll動態(tài)庫失敗\n");return 1;}}strncpy(fileName, file, strlen(file));File_flag = flag;DWORD dwThreadID;hThead = CreateThread(NULL, 0, readFileThread, 0, 0, &dwThreadID);return 0;}uint64_t CAPLEXPORT CAPLPASCAL getData(uint8_t *data)
{for (uint64_t i = 0; i < fileDataLength; i++){data[i] = fileData[i];}return fileDataLength;
}// ============================================================================
// CAPL_DLL_INFO_LIST : list of exported functions
// The first field is predefined and mustn't be changed!
// The list has to end with a {0,0} entry!
// New struct supporting function names with up to 50 characters
// ============================================================================
CAPL_DLL_INFO4 table[] = {
{CDLL_VERSION_NAME, (CAPL_FARCALL)CDLL_VERSION, "", "", CAPL_DLL_CDECL, 0xabcd, CDLL_EXPORT },{"bootloadReadFile", (CAPL_FARCALL)readFile, "BootloadFile","flag:1,s19;2,hex;3,bin",'U', 2, "CL", "\001\000", {"fileName","flag"}},{"bootloadGetData", (CAPL_FARCALL)getData, "BootloadFile","Suggested array length is 100000000",'U', 1, "B", "\001", {"fileData"}},
{0, 0}
};
CAPL調(diào)用dll
如上一條所說,dll調(diào)用dll可能會出現(xiàn)問題,需要先把需要的dll加載進去
通過下圖CANoe這里有一個介紹
1:我選擇了第一條方案,我的路徑是“C:\Program Files\Vector CANoe 15\Exec32”,僅作參考。
對應的dll獲取方式,自己寫一個Qt窗口工程,然后選擇32位的mingw的Release生成.exe文件。將此EXE文件復制粘貼到一個單獨空白的文件夾里面,通過下圖打開cmd窗口,進入到建立的目錄下,執(zhí)行windeployqt +“文件名”,獲取庫函數(shù),然后把.exe刪掉就可以了。看下下圖
2:將上面生成的dll,復制粘貼到路徑(C:\Program Files\Vector CANoe 15\Exec32 這個是我的,具體看自己)
CANoe實現(xiàn)
/*@!Encoding:936*/
includes
{#pragma library("capldll.dll")}variables
{}testcase readHEX()
{byte hahha[10000000];int i=0;qword testdd=0;write("哈哈哈 %d", bootloadReadFile("C:\\Users\\xiaoshuai\\Desktop\\test\\ED_C001_04_R2_CL_SV1.2_20221019.hex",2));testWaitForTimeout(1000);// bootloadGetData(hahha,testdd);write("當前數(shù)據(jù) %I64u",testdd=bootloadGetData(hahha));for(i=0;i<testdd;i=i+16){write("%d %02x",i/16,hahha[i]);}}void MainTest ()
{readHEX();
}
視頻演示
之后加
總結
以上說明完成,記住幾個踩坑點
1:vs2019中dll和sln放在同一個路徑
2:CANoe的數(shù)字不能用指針
3:CANoe記得放入DLL
可能有些是沒用的,可以自己嘗試