C++ problem z linkowaniem programu w BDS


(Karuzelnik) #1

Witam serdecznie,

próbuję skompilować listing z książki "USB praktyczne programowanie w Windows API".

Listing wygląda tak:

//---------------------------------------------------------------------------

include

include

include

include

include

pragma argsused

pragma hdrstop

define searchMaxDevices 10

// maksymalna liczba inteifejsow urzadzen

using namespace std;

// --------------------------------------------------------

template

inline void releaseMemory(T &x)

{

assert(x != NULL);

delete x;

x = NULL;

};

// --------------------------------------------------------

typedef USHORT USAGE, *PUSAGE;

typedef struct _HIDP_PREPARSED_DATA *PHIDP_PREPARSED_DATA;

//--------------------------------------------------------

typedef struct _HIDP_CAPS {//1

USAGE Usage;

USAGE UsagePage;

USHORT InputReportByteLength;

USHORT OutputReportByteLength;

USHORT FeatureReportByteLength;

USHORT Reserved[17];

USHORT NumberlinkCollectionNodes;

USHORT NumberInputButtonCaps;

USHORT NumberInputValueCaps;

USHORT NumberInputDataIndices;

USHORT NumberOutputButtonCaps;

USHORT NumberOutputValueCaps;

USHORT NumberOutputDataIndices;

USHORT NumberFeatureButtonCaps;

USHORT NumberFeatureValueCaps;

USHORT NumberFeatureDataIndices;

} HIDP_CAPS, *PHIDP_CAPS;

//---------------------------------------------------------

typedef struct _DEVICE_DATA {//1

TCHAR *HardwareId;

TCHAR *Path;

DWORD DeviceInstance;

HANDLE hidDeviceObject;

BYTE *inputReportBuffer;

USHORT inputReportByteLength;

USHORT outputReportByteLength;

USHORT featureReportByteLength;

PHIDP_PREPARSED_DATA preparsedData;

HIDP_CAPS capabilities;

} DEVICE_DATA, *PDEVICE_DATA;

// -------------------------------------------------------

class TUSBDevice {//1

private:

UINT fMemberIndex;

void displayError(const char* msg);

public:

PDEVICE_DATA deviceList;

BOOL getHidDeviceCapabilities(UINT memberIndex);

UINT setGetHidDeviceData();

HANDLE openHidUSBDevice(UINT memberIndex);

BOOL readUSBReport(UINT memberIndex);

BOOL closeHidUSBDevice(HANDLE devHandle);

TUSBDevice(UINT memberIndex);

~TUSBDevice();

};//0

//---------------------------------------------------------

TUSBDevice::TUSBDevice(UINT memberIndex){//1

fMemberIndex = memberIndex;

deviceList = (PDEVICE_DATA) new DEVICE_DATA[((fMemberIndex+1)*sizeof(DEVICE_DATA))];

};//0

//--------------------------------------------------------

TUSBDevice::~TUSBDevice()

{//1

releaseMemory(deviceList);

system("PAUSE");

};//0

//---------------------------------------------------------

void TUSBDevice::displayError(const char* msg)

{//1

cout << msg << endl;

system("PAUSE");

exit(0);

};//0

//--------------------------------------------------------

BOOL TUSBDevice::getHidDeviceCapabilities(UINT memberIndex)

{//1

HMODULE hHidLib;

bool status;

long (__stdcall* HidP_GetCaps)(IN PHIDP_PREPARSED_DATA PreparsedData, OUT PHIDP_CAPS Capabilities);

bool (__stdcall* HidD_GetPreparsedData)(IN HANDLE HidDeviceObject, OUT PHIDP_PREPARSED_DATA *PreparsedData);

bool (__stdcall* HidD_FreePreparsedData)(IN PHIDP_PREPARSED_DATA PreparsedData);

hHidLib = LoadLibrary("HID.DLL");

if(!hHidLib)

displayError("Blad dolaczenia biblioteki HID.DLL.");

(FARPROC&) HidP_GetCaps=GetProcAddress(hHidLib, "HidP_GetCaps");

(FARPROC&) HidD_GetPreparsedData=GetProcAddress(hHidLib, "HidD_GetPreparsedData");

(FARPROC&) HidD_FreePreparsedData=GetProcAddress(hHidLib, "HidD_FreePreparsedData");

if (!HidP_GetCaps || !HidD_GetPreparsedData || !HidD_FreePreparsedData)

{//2

FreeLibrary(hHidLib);

displayError("Nie znaleziono jednej lub wiecej funkcji eksportowych .\n");

};//1

status=HidD_GetPreparsedData(deviceList[memberIndex].hidDeviceObject,

&deviceList->preparsedData);

if(status){//2

HidP_GetCaps(deviceList->preparsedData, &deviceList->capabilities);

deviceList[memberIndex].inputReportByteLength = deviceList->capabilities.InputReportByteLength;

deviceList[memberIndex].outputReportByteLength = deviceList->capabilities.OutputReportByteLength;

deviceList[memberIndex].featureReportByteLength = deviceList->capabilities.FeatureReportByteLength;

HidD_FreePreparsedData(deviceList->preparsedData);

}//1

FreeLibrary(hHidLib);

return status;

};//0

// ---------------------------------------------------------

UINT TUSBDevice::setGetHidDeviceData()

{//1

DWORD propertyBufferSize = 0;

char *propertyBuffer = NULL;

HMODULE hHidLib;

SP_DEVINFO_DATA deviceInfoData;

HDEVINFO deviceInfoSet;

SP_INTERFACE_DEVICE_DATA deviceInterfaceData;

fMemberIndex = 0;

GUID classGuid;

PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL;

DWORD requiredSize = 0;

DWORD deviceInterfaceDetailDataSize = 0;

DWORD maxDevice = searchMaxDevices;

bool done = false;

void (__stdcall *HidD_GetHidGuid)(OUT LPGUID HidGuid);

hHidLib = LoadLibrary("HID.DLL");

if (!hHidLib)

displayError("Blad dolaczenia biblioteki HID.DLL.");

(FARPROC&) HidD_GetHidGuid = GetProcAddress(hHidLib,"HidD_GetHidGuid");

if (!HidD_GetHidGuid)

{//2

FreeLibrary(hHidLib);

displayError("Nie znaleziono identyfikatora GUID.");

};//1

HidD_GetHidGuid (&classGuid);

deviceInfoSet = SetupDiGetClassDevs(&classGuid, NULL, NULL,

(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));

deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

while(!done)

{//2

for(; fMemberIndex < maxDevice; fMemberIndex++)

{//3

if(SetupDiEnumDeviceInterfaces(deviceInfoSet,0,&classGuid,

fMemberIndex,&deviceInterfaceData))

{//4

SetupDiGetDeviceInterfaceDetail(deviceInfoSet,&deviceInterfaceData, NULL,0,&deviceInterfaceDetailDataSize, NULL);

requiredSize = deviceInterfaceDetailDataSize;

deviceInterfaceDetailData =(PSP_DEVICE_INTERFACE_DETAIL_DATA) new DWORD[deviceInterfaceDetailDataSize];

if(deviceInterfaceDetailData)

{//5

deviceInterfaceDetailData->cbSize= sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

}//4

else {//5

SetupDiDestroyDeviceInfoList(deviceInfoSet);

releaseMemory(deviceInterfaceDetailData);

return 0;

}//4

deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

if(!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, deviceInterfaceDetailData, deviceInterfaceDetailDataSize, &requiredSize, &deviceInfoData))

{//5

SetupDiDestroyDeviceInfoList(deviceInfoSet);

releaseMemory(deviceInterfaceDetailData);

return 0;

}//4

size_t nLen = strlen(deviceInterfaceDetailData->DevicePath) + 1;

deviceList[fMemberIndex].Path = new TCHAR[(nLen*sizeof(TCHAR))];

StrLCopy(deviceList[fMemberIndex].Path, deviceInterfaceDetailData->DevicePath, nLen);

deviceList[fMemberIndex].DeviceInstance = deviceInfoData.DevInst;

SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_HARDWAREID, NULL, NULL, 0, &propertyBufferSize);

// allokowanie pamieci dla bufora danych

propertyBuffer = new char[(propertyBufferSize*sizeof(TCHAR))];

SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_HARDWAREID, NULL, propertyBuffer, propertyBufferSize, NULL);

deviceList[fMemberIndex].HardwareId = propertyBuffer;

cout<<"\nDeviceList["<

releaseMemory(deviceInterfaceDetailData);

releaseMemory(propertyBuffer);

}//3

else {//4

if(ERROR_NO_MORE_ITEMS == GetLastError()){//5

done = TRUE;

break;

}//4

}//3

}//2

}//1

SetupDiDestroyDeviceInfoList(deviceInfoSet);

FreeLibrary(hHidLib);

return fMemberIndex;

}//0

//---------------------------------------------------------

HANDLE TUSBDevice::openHidUSBDevice(UINT memberIndex)

{//1

deviceList[memberIndex].hidDeviceObject == INVALID_HANDLE_VALUE;

deviceList[memberIndex].hidDeviceObject = CreateFile(deviceList[memberIndex].Path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING, FILE_FLAG_OVERLAPPED,NULL);

if(deviceList[memberIndex].hidDeviceObject != INVALID_HANDLE_VALUE)

return deviceList[memberIndex].hidDeviceObject;

else

return INVALID_HANDLE_VALUE;

}//0

// ---------------------------------------------------------

BOOL TUSBDevice::closeHidUSBDevice(HANDLE devHandle)

{//1

if((devHandle == 0) ||(devHandle == INVALID_HANDLE_VALUE))

{//2

return false;

}//1

else

return Win32Check(CloseHandle(devHandle));

};//0

//---------------------------------------------------------

BOOL TUSBDevice::readUSBReport(UINT memberIndex)

{//1

DWORD result = 0;

DWORD numberOfBytesRead = 0;

OVERLAPPED *overlapped = NULL;

if(overlapped == NULL){//2

overlapped = new OVERLAPPED;

overlapped->hEvent = CreateEvent(NULL, TRUE, TRUE, "");

overlapped->Offset = 0;

overlapped->OffsetHigh = 0;

}//1

memset(deviceList[memberIndex].inputReportBuffer, 0x00,

deviceList[memberIndex].inputReportByteLength);

if(!ReadFile(deviceList[memberIndex].hidDeviceObject,

deviceList[memberIndex].inputReportBuffer,

deviceList[memberIndex].inputReportByteLength,

&numberOfBytesRead, overlapped)) {//2

if(GetLastError() == ERROR_IO_PENDING) {//3

result = WaitForSingleObject(overlapped->hEvent, 100);

if(result == WAIT_TIMEOUT) {//4

CancelIo(deviceList[memberIndex].hidDeviceObject);

return false;

}//3

else

if(result == WAIT_FAILED){//4

displayError("Blad Odczytu danych.");

return false;

}//3

GetOverlappedResult(deviceList[memberIndex].hidDeviceObject,

overlapped, &numberOfBytesRead, FALSE);

}//2

else

displayError("Blad odczytu danych.");

}//1

ResetEvent(overlapped->hEvent);

if(numberOfBytesRead == (UINT)deviceList[memberIndex].inputReportByteLength){//2

for(USHORT i=0; i

printf("%d ", deviceList[memberIndex].inputReportBuffer_);_

printf("\n");

}//1

else {//2

printf ("Bledna liczba bajtow odebranych. \n" , numberOfBytesRead);

}//1

releaseMemory(overlapped);

return true;

}//0

//---------------------------------------------------------

int main() {//1

UINT interfaceIndex = 3; // numer istniejacego

//interfejsu urzadzenia HID

// stworzenie obiektu klasy TUSBDevice

TUSBDevice *usbDevice = new TUSBDevice(interfaceIndex);

// enumeracja aktualnie podlaczonych urzadzen klasy HiD

usbDevice->setGetHidDeviceData();

cout << "\nDeviceList["<

usbDevice->deviceList[interfaceIndex].Path << endl;

// otwarcie portu USB

usbDevice->openHidUSBDevice(interfaceIndex);

// odczyt wlasciwosci urzadzenia

if (usbDevice->getHidDeviceCapabilities(interfaceIndex)) {//2

_usbDevice->deviceList[interfaceIndex].inputReportBuffer = new _

BYTE[usbDevice->deviceList[interfaceIndex].inputReportByteLength];

while(true) { //3 cykliczny odczyt raportu wejsciowego

usbDevice->readUSBReport(interfaceIndex);

if(usbDevice->deviceList[interfaceIndex].inputReportBuffer[6]==64)

break;

}//2

_usbDevice->closeHidUSBDevice(usbDevice->deviceList[interfaceIndex]._

hidDeviceObject);

}//1

releaseMemory(usbDevice->deviceList[interfaceIndex].Path);

releaseMemory(usbDevice->deviceList[interfaceIndex].inputReportBuffer);

// wywolanie destruktora klasy TUSBDevice

releaseMemory(usbDevice);

return 0;

}//0

//---------------------------------------------------------------------------

Przy kompilacji otrzymuję błędy:

[Linker Error] Error: Unresolved external '__fastcall Sysutils::StrLCopy(char *, const char *, unsigned int)' referenced from D:\MOJE DOKUMENTY\BORLAND STUDIO PROJECTS\LISTING_7_2\LISTING_7_2.OBJ

[Linker Error] Error: Unresolved external '__fastcall Sysutils::Win32Check(int)' referenced from D:\MOJE DOKUMENTY\BORLAND STUDIO PROJECTS\LISTING_7_2\LISTING_7_2.OBJ

Wyszykałem podobnych problemów w necie i przypuszczam (może to za dużo powiedziane), że problem leży w odpowiednim zainicjowaniu obu funkcji.

Niestety nie umiem tego zrobić.

Po usunięciu odwołania do pliku sysutils.hpp kompilator zwraca błędy o nieznalezieniu funkcji.

Dziękuję za radę


(Chok) #2

Samo dołączenie pliku *.hpp, to połowa sukcesu. Musisz znaleźć w jakiej bibliotece znajdują się funkcje StrLCopy i Win32Check, a następnie dołączyć je do projektu (najłatwiej w Project Manager klikasz PPM, wybierasz Add i wskazujesz bibliotekę)