問題描述:
客戶給了我一個動態庫,就一個動態庫,讓你成功運行動態庫里面的文件。
1、我只有一個.dll文件,我要怎么用這個.dll文件里面的函數呢?
2、在成功加載這個.dll文件之后,出現了14001錯誤代碼之后,又應該怎么處理呢?
3、解決了14001錯誤代碼之后,又蹦出個運行時異常問題,又要怎么辦呢?
c++ loadlibrary錯誤14001
解決思路:
針對第一個問題:
我之前查了很久百度,CSDN,說什么都是教你怎么利用visual studio創建動態庫,然后使用動態庫。總而言之,他們所需要的,基本都是需要一個.h文件,一個.lib文件,一個.dll文件。那么對於沒有這三個文件的同學來說,這就很絕望了。你們說的再好,毛用沒有。我也是糾結了很久,最后才知道自己方向走偏了,你在百度的時候不要搜只有一個.dll文件,如何使用動態庫。你去搜,如何動態加載動態庫,一下子就很多。拿一個來用就好了。
針對第二個問題:
這個是在調用LoadLibrary()函數之后,使用int retValue = GetLastError();這句話來保存一個返回值,然后cout輸出出來看的時候發現它輸出的是14001錯誤碼。
這句話什么意思呢?就是缺少依賴庫或者缺少依賴庫的依賴庫或者某個依賴庫的版本不對。
什么意思?
先解釋下依賴庫是什么東西哈?比如我寫了一個a.cpp,然后我a.cpp里面包含了一個b.h文件,那么我這個b.h就是a.cpp所依賴的東西,只是現在b.h叫做a.cpp所依賴的頭文件;而當你要使用到庫的時候,你類比一下就知道,那個東西是我所缺少的庫,而那個庫是我所依賴的,所以叫做依賴庫。
再解釋下,如何知道自己所要調用的庫,到底是不是缺少了依賴庫呢?這里推薦大家使用Depens.exe這個程序。自己去網上搜,下載下來就好,使用方法我也不說了,簡單的要死。
舉個例子:
如果你發現我上面那個紅框里面有 黃色帶問號(一般比較短小,因為是人工命名的。注意:不包含下面這個黃框里面的這種什么API-MS-WIN什么的,這些是windows的東西不管)的東西,那就說明那些依賴庫是你缺少的。
再解釋下,如何確定自己不再缺少所依賴的庫了呢?如圖:
你將所缺少的庫放到你要使用的庫同級目錄下面,然后再拿這個depends.exe去檢測,你發現
像這種沒有一點黃色了之后,就可以判定為不缺少依賴庫了。
話說回來,我將所缺少的依賴庫放到同一目錄下之后有沒有解決問題呢?答案是沒有。依然是報錯14001.那我就去考慮是不是版本問題了,可是客戶就給了這么點版本給我,我能咋辦?於是,我去搜,一個CSDN博主告訴我要去下載2008版本的c++運行庫,最后安裝完畢,重啟完畢。OK!這個14001問題解決了。
第三個問題:
出現運行時異常怎么處理?百度上有人說運行時異常是由於多重繼承導致的,動態聯編和強制轉換的時候導致的問題,可是我也不知道這個動態庫里面有什么問題啊,是不?所以我就去刪除了一些特殊的符號,比如__stdcall這種東西,刪除完畢之后運行,成功!后來,同事告訴我,這是由於用戶的傳參規則和我們的傳參規則可能有些不同導致的。
就這樣解決了所有問題,成功運行。
現在附帶一個成功運行的代碼供大家參考:
#include <iostream>
#include <Windows.h>//這個頭文件必須包含。為什么?因為你后面要調用windows里面的函數句柄什么的!
int main()
{
using std::cout;
using std::endl;
typedef BOOL(*_InitPersoDLL) (ULONG);//之前就是在*前面加上了__stdcall導致的運行時異常,刪掉之后就好了。
typedef BOOL(*_StartPersoDLL)(ULONG, unsigned char *, unsigned int, unsigned char *, unsigned int *);
HMODULE m_histance = LoadLibraryA("C:\\xxx.dll");//這句話就是動態加載動態庫,參數是動態庫的路徑。我認為絕對路徑會好很多。
int nRet = GetLastError();//這句話可以拿到錯誤代碼。
cout << "retError:" << nRet << endl;
if (m_histance == NULL)//這邊建議,執行關鍵步驟之后都去判一下是否為NULL,否則不明不白就無了。
{
cout << "dll load failed!" << endl;
return -1;
}
_InitPersoDLL InitPersoDLL = (_InitPersoDLL)GetProcAddress(m_histance, "ModuleInit");//這話是用來拿到動態庫里面具體函數地址的,讓我們的函數指針指向它
if (InitPersoDLL == NULL)//持續判空
{
cout << "initFunction ERROR" << endl;
}
_InitPersoDLL ClosePersoDLL = (_InitPersoDLL)GetProcAddress(m_histance, "ModuleClose");
if (ClosePersoDLL == NULL)
{
cout << "closeFunction ERROR" << endl;
}
_StartPersoDLL StartPersoDLL = (_StartPersoDLL)GetProcAddress(m_histance, "ModuleStart");
if (StartPersoDLL == NULL)
{
cout << "startFunction ERROR" << endl;
}
bool initFlag = InitPersoDLL(4);//利用函數指針來調用函數
cout << "initFlag:" << initFlag << endl;
unsigned char dataIn[20] = "hello kiti";
unsigned char dataOut[1024] = {};
unsigned int outLength = 0;
bool startFlag = StartPersoDLL(4, dataIn, strlen((const char *)dataIn), dataOut, &outLength);
cout << "startFlag:" << startFlag << endl;
cout << dataOut << endl;
bool closeFlag = ClosePersoDLL(4);
cout << "closeFlag:" << closeFlag << endl;
std::cout << "Hello World!\n";
}