Click here to Skip to main content
15,919,613 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello. My problem is that i try to export a class from my DLL using an abstract interface. My DLL compiles just fine but despite adding project references from Properties in VS 2010 or including additional directories, i can't seem to open my header. They are under same folder by the way. Here is the code:

C++
//AtaClass.h : Abstract interface for DLL also header which i want to include
#include <string>

class AtaClass{
public:
	virtual std::string get_POT() = 0;
	virtual std::string get_RPM() = 0;
};


C++
//Bisikletdll.h main part of the DLL file
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>	//Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <Dbt.h>		//Need this for definitions of WM_DEVICECHANGE messages
#include <setupapi.h>	
#include <string>
#include "AtaClass.h"

using namespace std;

#define Cihaz_ID  "Vid_a0a1&Pid_4147"	 
#define __YAZI__ "Esetron USB Kart V1.0"

typedef GUID* LPGUID; 

typedef HDEVINFO (*SetupDiGetClassDevsUMPTR)(LPGUID, PCTSTR, HWND, DWORD);
typedef WINSETUPAPI BOOL (*SetupDiEnumDeviceInterfacesUMPTR)(HDEVINFO, PSP_DEVINFO_DATA, LPGUID, DWORD, PSP_DEVICE_INTERFACE_DATA);
typedef WINSETUPAPI BOOL (*SetupDiDestroyDeviceInfoListUMPTR)(HDEVINFO);
typedef WINSETUPAPI BOOL (*SetupDiEnumDeviceInfoUMPTR)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
typedef WINSETUPAPI BOOL (*SetupDiGetDeviceRegistryPropertyUMPTR)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
typedef WINSETUPAPI BOOL (*SetupDiSetDeviceRegistryPropertyUMPTR)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE*, DWORD);
typedef BOOL (*SetupDiGetDeviceInterfaceDetailUMPTR)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA, DWORD, PDWORD, PSP_DEVINFO_DATA);
typedef HDEVNOTIFY (*RegisterDeviceNotificationUMPTR)(HANDLE, LPVOID, DWORD);

typedef DWORD (*MPUSBGetDLLVersionPTR)(void);
typedef DWORD (*MPUSBGetDeviceCountPTR)(PCHAR);
typedef HANDLE (*MPUSBOpenPTR)(DWORD, PCHAR, PCHAR, DWORD, DWORD);
typedef BOOL (*MPUSBClosePTR)(HANDLE);
typedef DWORD (*MPUSBReadPTR)(HANDLE, PVOID, DWORD, PDWORD, DWORD);
typedef DWORD (*MPUSBWritePTR)(HANDLE, PVOID, DWORD, PDWORD, DWORD);
typedef DWORD (*MPUSBReadIntPTR)(HANDLE, PVOID, DWORD, PDWORD, DWORD);
typedef HDEVNOTIFY (*RegisterDeviceNotificationUMPTR)(HANDLE, LPVOID, DWORD);

//Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

//USB değişkenleri
BOOL AttachedState = false;		
BOOL AttachedButBroken = false;					
PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
HANDLE WriteHandleToUSBDevice = INVALID_HANDLE_VALUE;
HANDLE ReadHandleToUSBDevice = INVALID_HANDLE_VALUE;

unsigned char LED_durum = 0;
HANDLE  EP1INHandle = INVALID_HANDLE_VALUE;
HANDLE  EP1OUTHandle = INVALID_HANDLE_VALUE;
bool durum = false;
		
unsigned char gond_paket[65];	//Elemen sayısı, Uçnokta boyutu + 1
unsigned char gelen_paket[65];	 	
DWORD Gond_say;				
DWORD Gelen_say;

class Bisikletdll : public AtaClass
{
public:		
		SetupDiGetClassDevsUMPTR _SetupDiGetClassDevsUMPTR;
		SetupDiEnumDeviceInterfacesUMPTR _SetupDiEnumDeviceInterfacesUMPTR;
		SetupDiDestroyDeviceInfoListUMPTR _SetupDiDestroyDeviceInfoListUMPTR;
		SetupDiEnumDeviceInfoUMPTR _SetupDiEnumDeviceInfoUMPTR;
		SetupDiGetDeviceRegistryPropertyUMPTR _SetupDiGetDeviceRegistryPropertyUMPTR;
		SetupDiSetDeviceRegistryPropertyUMPTR _SetupDiSetDeviceRegistryPropertyUMPTR;
		SetupDiGetDeviceInterfaceDetailUMPTR _SetupDiGetDeviceInterfaceDetailUMPTR;
		RegisterDeviceNotificationUMPTR _RegisterDeviceNotificationUMPTR;

		MPUSBGetDLLVersionPTR _MPUSBGetDLLVersionPTR;
		MPUSBGetDeviceCountPTR _MPUSBGetDeviceCountPTR;
		MPUSBOpenPTR _MPUSBOpenPTR;
		MPUSBClosePTR _MPUSBClosePTR;
		MPUSBReadPTR _MPUSBReadPTR;
		MPUSBWritePTR _MPUSBWritePTR;
		MPUSBReadIntPTR _MPUSBReadIntPTR;
		RegisterDeviceNotificationUMPTR _RegisterDeviceNotificationUMPTR;

		DWORD ErrorStatusWrite;
		DWORD ErrorStatusRead;

		//Explicit Linking
		HINSTANCE hSetUpApi; 
		HINSTANCE hUser32;
		HINSTANCE hMPUSBAPI;

		string get_POT();
		string get_RPM();

		Bisikletdll();
		BOOL CheckIfPresentAndGetUSBDevicePath(void)
		{
			HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
			PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
			SP_DEVINFO_DATA DevInfoData;

			DWORD InterfaceIndex = 0;
			DWORD StatusLastError = 0;
			DWORD dwRegType;
			DWORD dwRegSize;
			DWORD StructureSize = 0;
			PBYTE PropertyValueBuffer;
			bool MatchFound = false;
			DWORD ErrorStatus;
			BOOL BoolStatus = FALSE;
			DWORD LoopCounter = 0;

			string DeviceIDToFind = Cihaz_ID;
			//First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
			DeviceInfoTable = _SetupDiGetClassDevsUMPTR(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
			
			//Now look through the list we just populated.  We are trying to see if any of them match our device. 
			while(true)
			{
				InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
				if(_SetupDiEnumDeviceInterfacesUMPTR(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
				{
					ErrorStatus = GetLastError();
					if(ERROR_NO_MORE_ITEMS == GetLastError())	//Did we reach the end of the list of matching devices in the DeviceInfoTable?
					{	//Cound not find the device.  Must not have been attached.
						_SetupDiDestroyDeviceInfoListUMPTR(DeviceInfoTable);	//Clean up the old structure we no longer need.
						return FALSE;		
					}
				}
			else	//Else some other kind of unknown error ocurred...
			{
				ErrorStatus = GetLastError();
				_SetupDiDestroyDeviceInfoListUMPTR(DeviceInfoTable);	//Clean up the old structure we no longer need.
				return FALSE;	
			}
			//Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
			//check to see if it is the correct device or not.

			//Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
			DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
			_SetupDiEnumDeviceInfoUMPTR(DeviceInfoTable, InterfaceIndex, &DevInfoData);

			//First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
			_SetupDiGetDeviceRegistryPropertyUMPTR(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

			//Allocate a buffer for the hardware ID.
			PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
			if(PropertyValueBuffer == NULL)	//if null, error, couldn't allocate enough memory
			{	//Can't really recover from this situation, just exit instead.
				_SetupDiDestroyDeviceInfoListUMPTR(DeviceInfoTable);	//Clean up the old structure we no longer need.
				return FALSE;		
			}

			//Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
			//REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
			//buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
			//format "Vid_04d8&Pid_003f".
			_SetupDiGetDeviceRegistryPropertyUMPTR(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

			//Now check if the first string in the hardware ID matches the device ID of my USB device.
			#ifdef UNICODE
			String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
			#else
			string* DeviceIDFromRegistry = new string((char *)PropertyValueBuffer);
			#endif
			free(PropertyValueBuffer);		//No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks

			//Now check if the hardware ID we are looking at contains the correct VID/PID
			if (std::string::npos != DeviceIDFromRegistry->find(DeviceIDToFind))
			{
				MatchFound = true;
			}
			if(MatchFound == true)
			{
				//Device must have been found.  Open WinUSB interface handle now.  In order to do this, we will need the actual device path first.
				//We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
				//time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
				//get the structure (after we have allocated enough memory for the structure.)
				DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
				//First call populates "StructureSize" with the correct value
				_SetupDiGetDeviceInterfaceDetailUMPTR(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);	
				DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));		//Allocate enough memory
				if(DetailedInterfaceDataStructure == NULL)	//if null, error, couldn't allocate enough memory
				{	//Can't really recover from this situation, just exit instead.
					_SetupDiDestroyDeviceInfoListUMPTR(DeviceInfoTable);	//Clean up the old structure we no longer need.
					return FALSE;		
				}
				DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
				//Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
				_SetupDiGetDeviceInterfaceDetailUMPTR(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 
				// Set Device Name
				byte *pbuf = new BYTE[sizeof(TEXT(__YAZI__))];
				pbuf = (byte*)TEXT(__YAZI__);
				_SetupDiSetDeviceRegistryPropertyUMPTR(DeviceInfoTable, &DevInfoData, SPDRP_FRIENDLYNAME , pbuf, sizeof(TEXT(__YAZI__)));
				
				//We now have the proper device path, and we can finally open a device handle to the device.
				//WinUSB requires the device handle to be opened with the FILE_FLAG_OVERLAPPED attribute.
				_SetupDiDestroyDeviceInfoListUMPTR(DeviceInfoTable);	//Clean up the old structure we no longer need.
				return TRUE;
			}

				InterfaceIndex++;	
				//Keep looping until we either find a device with matching VID and PID, or until we run out of devices to check.
				//However, just in case some unexpected error occurs, keep track of the number of loops executed.
				//If the number of loops exceeds a very large number, exit anyway, to prevent inadvertent infinite looping.				
				LoopCounter++;
				if(LoopCounter == 10000000)	//Surely there aren't more than 10 million devices attached to any forseeable PC...
				{
					return FALSE;
				}
			}
			
		}
	
protected:
	/// <summary>
	/// Clean up any resources being used.
	/// </summary>
	~Bisikletdll()
	{
		//Close the read/write handles, if they are currently open.
		if(AttachedState == TRUE)
		{
			CloseHandle(WriteHandleToUSBDevice);
			CloseHandle(ReadHandleToUSBDevice);
		}
	}

};


string Bisikletdll::get_RPM(){
		gond_paket[0] = 0;		// HID sınıfında ilk eleman Rapor ID 'sini tutar, cihaza gönderilmez
		gond_paket[1] = 160;
		gond_paket[2] = 0;
		gond_paket[3] = 0;
		
		string str;

		for(unsigned char i = 4; i <65; i++)
			gond_paket[i] = 0xFF;

		WriteFile(WriteHandleToUSBDevice, &gond_paket, 65, &Gond_say, 0);

		if (ReadFile(ReadHandleToUSBDevice,&gelen_paket,65,&Gelen_say,0))
		{
			if (gelen_paket[1] == 0xBA)
			{
				return str = gelen_paket[3];
			}
		}
}
string	Bisikletdll::get_POT(){
		gond_paket[0] = 0;		// HID sınıfında ilk eleman Rapor ID 'sini tutar, cihaza gönderilmez
		gond_paket[1] = 160;
		gond_paket[2] = 0;
		gond_paket[3] = 0;
							 
		string str;

		for(unsigned char i = 4; i <65; i++)
			gond_paket[i] = 0xFF;

		WriteFile(WriteHandleToUSBDevice, &gond_paket, 65, &Gond_say, 0);
		
		if (ReadFile(ReadHandleToUSBDevice,&gelen_paket,65,&Gelen_say,0))
		{
			if (gelen_paket[1] == 0xBA)
			{
				return str = gelen_paket[5];
			}
		}
}


Bisikletdll::Bisikletdll(){
	hSetUpApi = LoadLibrary("setupapi.dll");
	hUser32 = LoadLibrary("user32.dll");
	hMPUSBAPI = LoadLibrary("MPUSBAPI.dll");

	_SetupDiGetClassDevsUMPTR = (SetupDiGetClassDevsUMPTR)GetProcAddress(hSetUpApi, "SetupDiGetClassDevs");
	_SetupDiEnumDeviceInterfacesUMPTR = (SetupDiEnumDeviceInterfacesUMPTR)GetProcAddress(hSetUpApi, "SetupDiEnumDeviceInterfaces");
	_SetupDiDestroyDeviceInfoListUMPTR = (SetupDiDestroyDeviceInfoListUMPTR)GetProcAddress(hSetUpApi, "SetupDiDestroyDeviceInfoList");
	_SetupDiEnumDeviceInfoUMPTR = (SetupDiEnumDeviceInfoUMPTR)GetProcAddress(hSetUpApi, "SetupDiEnumDeviceInfo");
	_SetupDiGetDeviceRegistryPropertyUMPTR = (SetupDiGetDeviceRegistryPropertyUMPTR)GetProcAddress(hSetUpApi, "SetupDiGetDeviceRegistryProperty");
	_SetupDiSetDeviceRegistryPropertyUMPTR = (SetupDiSetDeviceRegistryPropertyUMPTR)GetProcAddress(hSetUpApi, "SetupDiSetDeviceRegistryProperty");
	_SetupDiGetDeviceInterfaceDetailUMPTR = (SetupDiGetDeviceInterfaceDetailUMPTR)GetProcAddress(hSetUpApi, "SetupDiGetDeviceInterfaceDetail");

	_MPUSBGetDLLVersionPTR = (MPUSBGetDLLVersionPTR)GetProcAddress(hMPUSBAPI, "_MPUSBGetDLLVersion");
	_MPUSBGetDeviceCountPTR = (MPUSBGetDeviceCountPTR)GetProcAddress(hMPUSBAPI, "_MPUSBGetDeviceCount");
	_MPUSBOpenPTR = (MPUSBOpenPTR)GetProcAddress(hMPUSBAPI, "_MPUSBOpen");
	_MPUSBClosePTR = (MPUSBClosePTR)GetProcAddress(hMPUSBAPI, "_MPUSBClose");
	_MPUSBReadPTR = (MPUSBReadPTR)GetProcAddress(hMPUSBAPI, "_MPUSBRead");
	_MPUSBWritePTR = (MPUSBWritePTR)GetProcAddress(hMPUSBAPI, "_MPUSBWrite");
	_MPUSBReadIntPTR = (MPUSBReadIntPTR)GetProcAddress(hMPUSBAPI, "_MPUSBReadInt");

	DEV_BROADCAST_DEVICEINTERFACE MyDeviceBroadcastHeader;// = new DEV_BROADCAST_HDR;
	MyDeviceBroadcastHeader.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
	MyDeviceBroadcastHeader.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
	MyDeviceBroadcastHeader.dbcc_reserved = 0;	//Reserved says not to use...
	MyDeviceBroadcastHeader.dbcc_classguid = InterfaceClassGuid;

	if(CheckIfPresentAndGetUSBDevicePath())	//Cihazı ara
	{
		DWORD ErrorStatusWrite;
		DWORD ErrorStatusRead;

		WriteHandleToUSBDevice = CreateFile(DetailedInterfaceDataStructure->DevicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
		ErrorStatusWrite = GetLastError();
		ReadHandleToUSBDevice = CreateFile(DetailedInterfaceDataStructure->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
		ErrorStatusRead = GetLastError();

		if((ErrorStatusWrite == ERROR_SUCCESS) && (ErrorStatusRead == ERROR_SUCCESS))
		{
			AttachedState = TRUE;		
			AttachedButBroken = FALSE;
			//okay
		}

		else //yazma ya da okuma işlemlerinden biri başarasız olursa
		{
			AttachedState = FALSE;		
			AttachedButBroken = TRUE;	
			if(ErrorStatusWrite == ERROR_SUCCESS)//Açık bağlantıları kapat
				CloseHandle(WriteHandleToUSBDevice);
			if(ErrorStatusRead == ERROR_SUCCESS)
				CloseHandle(ReadHandleToUSBDevice);
		    //err1();					 
		}
	}
	else	
	{
		AttachedState = FALSE;
		AttachedButBroken = FALSE;
		//err2();
	}
}

//Exporting DLL class through interface
extern "C" __declspec(dllexport) AtaClass* APIENTRY create_AtaClass()
{
    return new Bisikletdll;
}


C++
// TestdllBisiklet.cpp : Defines the entry point for the console application.
// Compiler errors start here
#include "stdafx.h"
#include "AtaClass.h"  //can't include that
#include <Windows.h>
#include <iostream>

using namespace std;

typedef AtaClass* (APIENTRY *ataclass_factory)();

int main()
{
	HINSTANCE dll_handle = ::LoadLibrary(TEXT("Bisikletdll.dll");
	if(!dll_handle){
		cerr << "Yukleme basarisiz!";
		return 1;
	}
	
	ataclass_factory factory_func = reinterpret_cast<ataclass_factory>(::GetProcAddress(dll_handle, "create_AtaClass"));

	if (!factory_func) {
        cerr << "create_AtaClass DLL'den yuklenemedi!\n";
        ::FreeLibrary(dll_handle);
        return 1;
    }

	AtaClass* instance = factory_func();

	string t = instance->get_POT();
	cout <<	"POT : " << t << endl;
	string v = instance->get_RPM();
	cout << "RPM : " << v << endl;

	return 0;
}


Apologies for the lengthy code but i presumed you needed every detail. It's usual USB programming. Thanks for help.
Posted
Updated 10-Feb-13 22:25pm
v2
Comments
Richard MacCutchan 11-Feb-13 4:22am    
Which header can you not include and why? Please show the error messages you receive when you try to build the project.
YourAverageCoder 11-Feb-13 4:27am    
AtaClass.h the abstract interface header i want to include. The compiler gives me "cannot open source code 'AtaClass.h'" error even though they are under the same solution albeit different projects.
Richard MacCutchan 11-Feb-13 4:40am    
Check that you have set the correct directory paths in your project's include properties.

1 solution

use relative paths. E.g., say the solution is organised like this:

Solution Folder
 |_ [Ata]              --> This folder contains AtaClass.h
   |_ Ata.vcproj
   |_ AtaClass.h
 |_ [Bisikletdll]      --> This folder is where your other dll
   |_ Bisikletdll.vcproj
   |_ Bisikletdll.h
   |_ Bisikletdll.cpp 


Although the both projects are in the same solution, physically they are located in different folders. So, in you case use this:

C++
//Bisikletdll.h main part of the DLL file
....
#include "..\Ata\AtaClass.h"


In the path definition above .. will direct one folder up (you will end up in the Solution Folder) and then relative to the Solution folder you go to Ata (father in turks languages BTW) subfolder, and then to AtaClass.h file
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900