各種函數鏈接庫錯誤(無法解析的外部符號)
本人新手對於如何包含動態鏈接庫也不是很了解,請問這種情況應該怎麼配置?
代碼如下,就是想根據vID pID找到指定的設備。
函數中SetupDi······,Hid_Get...都報無法解析錯誤
(CSDN新人,1個C幣是全部家當了,跪求)
#include "stdafx.h"
#include "afxwinappex.h"
#include "afxdialogex.h"
#include "CommTest.h"
#include "MainFrm.h"
#include "CommTestDoc.h"
#include "CommTestView.h"
extern "C" {
//declare the C libraries used
#include "setupAPI.h"
#include "hidsdi.h"
}
BOOL CCommTestWindow::DeviceOpen(HANDLE &handle, WORD wVID, WORD wPID)
{
BOOL bRet = FALSE;
GUID hidGuid;
HDEVINFO hardwareDeviceInfo;
SP_INTERFACE_DEVICE_DATA deviceInfoData;
PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData = NULL;
ULONG predictedLength = 0;
ULONG requiredLength = 0;
CloseHandle(handle);
handle = INVALID_HANDLE_VALUE;
deviceInfoData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
HidD_GetHidGuid(&hidGuid);
hardwareDeviceInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
for (int i = 0; i<128; i++)
{
if (!SetupDiEnumDeviceInterfaces(hardwareDeviceInfo, 0, &hidGuid, i, &deviceInfoData)) continue;
SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo, &deviceInfoData, NULL, 0, &requiredLength, NULL);
predictedLength = requiredLength;
functionClassDeviceData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(predictedLength);
if (!functionClassDeviceData) continue;
functionClassDeviceData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo, &deviceInfoData, functionClassDeviceData, predictedLength, &requiredLength, NULL)) break;
handle = CreateFile(functionClassDeviceData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (handle != INVALID_HANDLE_VALUE)
{
HIDD_ATTRIBUTES attri;
HidD_GetAttributes(handle, &attri);
if ((attri.VendorID == wVID) && (attri.ProductID == wPID))
{
bRet = TRUE;
break;
}
CloseHandle(handle);
handle = INVALID_HANDLE_VALUE;
}
}
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
return bRet;
}
原因一:用戶自定義的類中的函數聲明與函數定義分開寫時,函數名寫的不一致,往往初學者比較容易犯這樣的毛病,比如,在類的頭文件Point.h裡聲明了void setX(int aX);函數,在Point.cpp文件中寫該函數的定義時確寫成了void Point::setx(int aX){},由於C++語言是區分大小寫的編程語言,所以在編譯時認定為只有該函數setX的聲明,沒有其定義,當然這種情況往往容易發現錯誤,因為計算機會先報語法聲明錯誤,告知setx函數沒有在類Point中聲明,然而,可怕的是在.h文件裡聲明了setX函數,卻忘記了在.cpp文件裡定義,這時,在程序中調用過幾次setX函數就會出現幾個link鏈接錯誤,初學者往往由於大量的鏈接錯誤而灰心喪氣,其實如果知道原因了修改起來並不難。
避錯方案:將聲明好的類寫好後,復制,然後粘貼到.cpp文件中完成其定義過程,需要提醒的是,注意去掉每個函數聲明後面的分號。
原因二:未引入鏈接庫.lib文件,這個多發生在使用第三方開發庫的情況下,比如,我在博客中系列提到的SDL開發,開發時需要在編譯的時候鏈接SDL提供的lib庫,如果沒有通過配置的方式(配置的方法請參考我前面SDL配置相關文章,這裡不做贅述)添加相關.lib文件或者通過#pragma comment(lib, 'SDL.lib')提供lib的鏈接,那麼計算機會因為找不到所調用函數的代碼段(這種情況下,只有頭文件,代碼段被編譯好了放在.lib文件裡)而報link錯誤,改正的方法就不言而喻了。
避錯方案:先看自己的工程有沒有用到第三方開發環境,如果用到了,請先把這些配好,再開始後續的開發工作。另外,不是只有第三方開發環境才需要配置相應的 .lib文件,當我們在VS2005/2008(暫且以他們為例,其它同理)中,按alt+F7打開工程屬性頁後,點選配置屬性-->鏈接器-->輸入,可以看到默認添加好的lib文件如下:
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib
在開發過程中如果用到之外的庫(這種情況在學習C++時很少遇到)就必須要手動添加了。
原因三:沒有將項目需要的頭文件、源文件都加入項目中。這個經常會有人犯,可以進行排查。
避錯方案:細心,另外就是在寫程序時發現自己用到了新的類型就立刻把該類型的頭文件添加(其實就是#include進來),如果寫完某對象在其後加“.”後IDE環境不能智能彈出數據成員和成員函數,那麼也要注意了,一般是因為你沒有添加相應的頭文件造成的。當然IDE環境出問題的情況也有,畢竟很少,區別對待即可。
原因四:當__declspec(dllexport)函數與inline函數混用並要生成.exe的工程也會偶然產生這種錯誤,這種錯誤我在最近做實驗的時候遇到,目前具體原因不詳,在新的工程中做寫簡單代碼測試後也沒有再產生link錯誤,最後解決的辦法是去掉了inline(本身這個是建議性的語法,所以去掉後不影響編譯),結果問題就解決了,也順利通過了。
避錯方案:在寫exe工程時,不要寫__declspec(dllexport)符號,本身這個符號是編譯dll時使用的導出符號,符號用的多了難免沖突,在不明原因的情況下也很難排錯。