1. 程式人生 > >DLL介面的實現(COM結構思想)二

DLL介面的實現(COM結構思想)二

程式碼的實現部分如下:

介面標頭檔案 IUnknowService.h

#include<iostream>
#include<string>
using namespace std;

#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif

//IUnknowService 介面主要是為了查詢這個元件裡實現了哪些介面。
//如果指定查詢的介面不存在(可能目前使用的是這個元件的早期的版本),
//那麼返回值是NULL。

class IUnknowService
{
public:
	virtual void QueryInterface(string type,void** ppv) = 0;
	virtual void  Add() = 0;
	virtual void  Release() = 0;
};

//介面的實現實際上也是一箇中間層。實際提供下載服務的是其他一些類。
class IPerson:public IUnknowService
{
public:
	virtual void Eat() = 0;
};
class IBook:public IUnknowService
{
public:
	virtual void Read() = 0;
};


這邊的IUnknowService與標準的IUnknow的定義不同,標準的是有返回值的,而且第一個引數是個ID。這裡只是借用COM的思想來簡單實現下。IPerson 和 IBook 是兩個不同的介面類。可以這樣理解,不同的介面類可以是不同時期發行的DLL庫的不同版本,這樣只要同時繼承了這些版本的介面並可以實現版本的相容。

介面實現類 InterFace.h

#include"IUnknowService.h"

class CTeacher:public IPerson,IBook
{
public:
	CTeacher():m_refCount(0){	}
	virtual void QueryInterface(string type,void** ppv);
	virtual void Add();
	virtual void Release();
	virtual void Eat();
	virtual void Read();
	int GetrefCount() { return m_refCount; }
private:
	int m_refCount;  //引用計數
};
void CTeacher::QueryInterface(string type,void** ppv)
{
	if("Person" == type)
		*ppv = static_cast<IPerson*> (this);
	else if("Book" == type)
		*ppv = static_cast<IBook*>(this);
	if(*ppv)
		static_cast<IUnknowService*>(*ppv)->Add();
}
void CTeacher::Release()
{
	m_refCount--;
	if(0 == m_refCount)
	{
		delete this;
		printf("Component destroy...\n");
	}
	else
		printf("引用計數為:%d \n",m_refCount);
}
void CTeacher::Add(){	m_refCount++; printf("引用計數為:%d \n",m_refCount); }
void CTeacher::Eat(){	printf("Eatting!\n"); }
void CTeacher::Read(){	printf("Reading!\n"); }

這個是介面的實現類,m_refCount用來儲存引用計數。

DLL的匯出:main.cpp

#include"InterFace.h"

extern"C" CLASS_DECLSPEC IUnknowService* Create();

IUnknowService* Create()
{
	IUnknowService* _interface = static_cast<IPerson*>(new CTeacher);
	_interface->Add();
	return _interface;
}


在另一個工程中包含介面標頭檔案 IUnknowService.cpp,包含對應生成的DLL和.lib

DLL的匯入:main.cpp

#include<iostream>
#include"IUnknowService.h"
using namespace std;

#pragma comment(lib,"Com.lib")
extern"C" CLASS_DECLSPEC IUnknowService* Create();

void main()
{
	IUnknowService *obj = Create();
	IPerson* person1 = NULL;
	IBook*   book1 = NULL;
	obj->QueryInterface("Person",(void**)&person1);
	person1->Eat();
	obj->QueryInterface("Book",(void**)&book1);
	book1->Read();
	person1->Release();
	book1->Release();
	obj->Release();
}

這裡說明一下QueryInterface的第二個引數 void**ppv,我們呼叫QueryInterface("Person",(void**)&person1)是可知這裡相當於ppv=&person1,也就是ppv指向了person1。因此*ppv就成了person,void**ppv成了 void *person。

好的,到此這個COM結構思想簡單實現DLL介面已經結束了,下面是輸出的結果: