KPU – 02 Write DLL using interfaces

This is a more tricky exercise – create an application with two projects, using global interfaces and communicate through them in a DLL-file.

Interfaces

//IappUtil.hpp
#pragma once
#include
using namespace std;

class IAppUtil
{
public:
  virtual string GetName() = 0;
  virtual string MyAddString(string str1, string str2) = 0;
};

Nothing fancy. This class is full virtual and must be implemented.

//IDllClass.hpp
#pragma once

class IDLLclass
{
public:
  virtual bool Init(IAppUtil* pUtil) = 0;
  virtual bool Run() = 0;
  virtual void TearDown() = 0;
};

Full virtual class with a pointer to IAppUtil.

The DLL file

Now create a project for the DLL file.

//DllClass.h
#pragma once
#include "../IAppUtil.hpp"
#include "../IDLLclass.hpp"

class DllClass : public IDLLclass
{
public:
	DllClass();
	~DllClass();
	virtual bool Init(IAppUtil* pUtil);
	virtual bool Run();
	virtual void TearDown();

private:
	IAppUtil* _pAppUtil;
	char* _pName;
};

Inheriting from IDLLclass.

The implementation is kept simple;

#include "stdafx.h"
#include "DllClass.h"
#include

using namespace std;

DllClass::DllClass()
{
	std::cout << "Creating a new class" << std::endl;
}

DllClass::~DllClass()
{
	TearDown();
}

bool DllClass::Init(IAppUtil* pUtil)
{
	_pAppUtil = pUtil;
	std::cout << "Initialted the DLL Class" << std::endl;
	return true;
}

bool DllClass::Run()
{
	std::cout << "DllClass is now running" << std::endl;
	return true;
}

void DllClass::TearDown()
{
	std::cout << "Closing this class object" << std::endl;
	delete _pAppUtil;
}

Now a API the DllClass can be accessed through:

//Global.h
#pragma once
#define DLLCLASS_EXPORT __declspec(dllexport)
#define DLLCLASS_IMPORT __declspec(dllimport)

#include "DllClass.h"

extern "C"
{
	namespace GLOBAL
	{
		DLLCLASS_EXPORT DllClass* CreateDllObject(void);
		DLLCLASS_EXPORT void DeleteDllObj(DllClass* obj);
	}
}

And simple implementation for the Global class:

//Global.cpp
#include "stdafx.h"
#include "Global.h"

extern "C"
{
	namespace GLOBAL
	{

		DLLCLASS_EXPORT DllClass* CreateDllObject()
		{
			DllClass* obj = new DllClass();
			return obj;
		}

		DLLCLASS_EXPORT void DeleteDllObj(DllClass* obj)
		{
			delete obj;
		}
	}
}

We can now get an object of the DllClass and delete it again.

Using the DLL file

We inherit from IAppUtil and implement its methods:

//AppUtilImp.h
#pragma once
#include "../IAppUtil.hpp"

class AppUtillMp : public IAppUtil
{
public:
	AppUtillMp(void);
	AppUtillMp(string name);
	~AppUtillMp();

	virtual string GetName();
	virtual string MyAddString(string str1, string str2);
private:
	string m_name;
};
//AppUtilImpl.cpp
#include "stdafx.h"
#include "AppUtillMp.h"

AppUtillMp::AppUtillMp()
{}

AppUtillMp::AppUtillMp(string name)
{
	m_name = name;
}

string AppUtillMp::GetName()
{
	return m_name;
}

AppUtillMp::~AppUtillMp()
{}

string AppUtillMp::MyAddString(string str1, string str2)
{
	return str1 + str2;
}

Now we can access the DLL file the same way we did in the last exercise.
We will do so by asking the user which DLL to use, validate if we can find it and use it and call the functions:

//main.cpp
#include "stdafx.h"
#include "AppUtillMp.h"
#include "../IDLLclass.hpp"

#include
#include
#include
#include
#include

using namespace std;

typedef IDLLclass* (*DLLFUNC1)(void);
typedef void (*DLLFUNC2)(IDLLclass* obj);

DLLFUNC1 func1;    // Function pointer
DLLFUNC2 func2;    // Function pointer
HINSTANCE hDLL = NULL;

int _tmain(int argc, _TCHAR* argv[])
{
	while(hDLL == NULL)
	{
		cout << "Please enter the location of the .dll"
			<< " file without the '.dll' extention" << endl; 		wstring input; 		wcin >> input;

		wstring dllFile;
		dllFile.assign(input.begin(), input.end());

		hDLL = LoadLibrary(dllFile.c_str());
	}

	func1 = (DLLFUNC1)GetProcAddress(hDLL, "CreateDllObject");
	func2 = (DLLFUNC2)GetProcAddress(hDLL, "DeleteDllObj");

	if (func1 == NULL || func2 == NULL)
	{
		cout << "One of your functions were not loaded" << endl; 		getchar(); 		FreeLibrary(hDLL); 		return -1; 	} 	else 	{ 		IDLLclass* obj = func1(); 		AppUtillMp* obj2 = new AppUtillMp("User"); 		string theName = obj2->GetName();
		cout << theName << endl; 		string newName = obj2->MyAddString(theName, "name");
		cout << newName << endl; 		obj->Init(obj2);
		bool isRunning = obj->Run();
		if(isRunning == true)
			std::cout << "It is... " << std::endl; 		obj->TearDown();

		_getch();
	}
	FreeLibrary(hDLL);
}

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>