Author : Gaz Iqbal
Page : << Previous 2
apart from the constructor and destructor. The interface will be a typical C/C++ structure containing only pure virtual functions. The actual class in the DLL will inherit from this struct and it will implement the functions defined in it. Now to allow access to this class from the client, all we need to do is to export a standard C-style function that instantiates the class, casts it to the interface so that the client can use it, and returns it. Another function should be exported that deletes the interface once the client is done with it. A sample implementation is given below.
//==================================
//Dlls .def file
LIBRARY myinterface.dll
DESCRIPTION 'provides interface to I_MyInterface
EXPORTS
GetMyInterface
FreeMyInterface
//===================================
//Shared header between Dll and Client which defines the interface
//I_MyInterface.h
struct I_MyInterface
{
virtual bool Init(int parms)=0;
virtual bool Release()=0;
virtual void DoStuff() =0;
};
/*
Declarations for the Dlls exported functions and typedef'ed function
pointers to make it easier to load them. Note the extern "C" which
tell the compiler to use C-style linkage for these functions
*/
extern "C"
{
HRESULT GetMyInterface(I_MyInterface ** pInterface);
typedef HRESULT (*GETINTERFACE)(I_MyInterface ** pInterface);
HRESULT FreeMyInterface(I_MyInterface ** pInterface);
typedef HRESULT (*FREEINTERFACE)(I_MyInterface ** pInterface);
}
//====================================
//Dlls implementation of the interface
// MyInterface.h
class CMyClass: public I_MyInterface
{
public:
bool Init(int parms);
bool Release();
void DoStuff();
CMyClass();
~CMyClass();
//any other member funcs
............
private:
//any member vars
............
};
//======================================
//Dlls exported functions which create and delete the interface
//Dllmain.h
HRESULT GetMyInterface(I_MyInterface ** pInterface)
{
if(!*pInterface)
{
*pInterface= new CMyClass;
return S_OK;
}
return E_FAIL;
}
HRESULT FreeMyInterface(I_MyInterface ** pInterface)
{
if(!*pInterface)
return E_FAIL;
delete *pInterface;
*pInterface= 0;
return S_OK;
}
//=====================================
//Client code
//How to load the interface and call functions
GETINTERFACE pfnInterface=0; //pointer to GetMyInterface function
I_MyInterface * pInterface =0; //pointer to MyInterface struct
HINSTANCE hMyDll = ::LoadLibrary("myinterface.dll");
if(hMyDll != NULL)
{
//Get the functions address
pfnInterface= (GETINTERFACE)::GetProcAddress(hMyDll,"GetMyInterface");
//Release Dll if we werent able to get the function
if(pfnInterface == 0)
{
::FreeLibrary(hMyDll);
return;
}
//Call the Function
HRESULT hr = pfnInterface(&pInterface);
//Release if it didnt work
if(FAILED(hr))
{
::FreeLibrary(hMyDll);
return;
}
//Interface was loaded, we can now call functions
pInterface->Init(1);
pInterface->DoStuff();
pInterface->Release();
//How to release the interface
FREEINTERFACE pfnFree = (FREEINTERFACE )::GetProcAddress(hMyDll,"FreeMyInterface");
if(pfnFree != 0)
pfnFree(&hMyDll);
//Release the DLL if we dont have any use for it now
::FreeLibrary(hMyDll);
}
Ths information should be enough to get you really comfortable when using DLLs. Feel free to contact me if you have any questions, corrections or improvements. Happy coding.
Gaz Iqbal
Page : << Previous 2