#include "stdafx.h"
#include "expclass.h"
#include "forcecast.h"
#include "classldr.h"
#include <malloc.h>

int main(int argc, char* argv[])
{

	TCHAR szDllPath[MAX_PATH];
	HMODULE hMod;
	
	do
	{
		_tprintf(TEXT("Please enter the dll to load the class from:\n"));
		_tscanf(TEXT("%s"), szDllPath);
	}
	while ((hMod = LoadLibrary(szDllPath)) ? 
				false : 
				_tprintf(TEXT("Failed to Load the dll. GetLastError returns: 0x%X\n"), GetLastError()));

	
	/* Virtual Function table method */
	_tprintf(TEXT("Importing by Virtual Function Table:\n\n"));
	
	typedef A* (*PFNCreateA1)();
	typedef A* (*PFNCreateA2)(int);

/*************************************************************************/	
	_tprintf(TEXT("Creating an Object of A through Default Constructor\n"));

	PFNCreateA1 pfnCreateA1 = (PFNCreateA1)GetProcAddress(hMod, TEXT("CreateObjectofA1"));

	A* a = (pfnCreateA1)();

	a->SetNum(1);

	_tprintf(TEXT("Value of m_nNum in a is %d\n"), a->GetNum());
	
	delete a;
	
	a = NULL;
/*************************************************************************/	
	_tprintf(TEXT("Creating an Object of A through Other Constructor\n"));
	
	PFNCreateA2 pfnCreateA2 = (PFNCreateA2)GetProcAddress(hMod, TEXT("CreateObjectofA2"));

	a = (pfnCreateA2)(2);

	_tprintf(TEXT("Value of m_nNum in a is %d\n"), a->GetNum());

	a->SetNum(1);

	_tprintf(TEXT("Value of m_nNum in a is %d\n"), a->GetNum());
	
	delete a;
	
/*************************************************************************/

	
	_tprintf(TEXT("\nImporting by Typecasting Pointers:\n\n"));

	
	typedef void (A::*PfnConstructorOfA1)();
	typedef void (A::*PfnConstructorOfA2)(int);
	typedef void (A::*PfnDestructorOfA)();
	typedef void (A::*PfnSetNumOfA)(int);
	typedef int	 (A::*PfnGetNumOfA)();
	
	A* a1 = (A*)_alloca(sizeof(A));

	PfnConstructorOfA1 pfnConsA = force_cast<PfnConstructorOfA1>(GetProcAddress(hMod, TEXT("ConstructorOfA1")));

	(a1->*pfnConsA)();

	PfnSetNumOfA pfnSetNumA = force_cast<PfnSetNumOfA>(GetProcAddress(hMod, TEXT("SetNumOfA")));

	(a1->*pfnSetNumA)(1);
	
	PfnGetNumOfA pfnGetNumA = force_cast<PfnGetNumOfA>(GetProcAddress(hMod, TEXT("GetNumOfA")));

	_tprintf(TEXT("Value of m_nNum in a is %d\n"), (a1->*pfnGetNumA)());


	PfnDestructorOfA pfnDestA = force_cast<PfnDestructorOfA>(GetProcAddress(hMod, TEXT("DestructorOfA")));

	(a1->*pfnDestA)();

/*************************************************************************/

	_tprintf(TEXT("\nImporting by Delegation in Constructor and Destructor:\n\n"));

	ClassLoader<A>::s_hMod = hMod;
	
	A a2;

	a2.SetNum(1);

	_tprintf(TEXT("Value of m_nNum in a is %d\n"), a2.GetNum());
	

	A* pA = new A(1);

	pA->SetNum(1);

	delete pA;

/*************************************************************************/

		

	return 0;
}