Topic : Using Interfaces with Dlls
Author : Gaz Iqbal
Page : << Previous 2  
Go to page :


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