首页 > 其他 > 详细

COM组件入门(一)

时间:2014-08-13 18:52:57      阅读:327      评论:0      收藏:0      [点我收藏+]

最近需要用到COM组件的知识,看了看COM编程指南,感觉还不错,把我的学习心得记录下来。这是我根据教程写的demo

StopWatch接口实现部分,接口部分我的项目是动态库,主要源码如下:

完整demo见:http://download.csdn.net/detail/davidsu33/7750101

stopwatch.h

#pragma once

#include <Windows.h>
#include <MMSystem.h>
#include <Unknwn.h>
#include <WinBase.h>
#include "timer_i.h"

class stopwatcher
{
public:
	stopwatcher(void);
	~stopwatcher(void);
};

class IStopWatch : public IUnknown
{
public:
	//virtual unsigned long _stdcall Release() = 0;
	virtual HRESULT _stdcall Start() = 0;
	virtual HRESULT _stdcall ElaspedTime(float *elaspedtime) = 0;
};

class CStopWatch : public IStopWatch
{
public:
	CStopWatch()
	{
		m_nRefValue = 0;
		m_nFreq.QuadPart = 0;
		QueryPerformanceFrequency(&m_nFreq);
		AddRef();
	}
public:
	//virtual unsigned long _stdcall Release()
	//{
	//	delete this;
	//	return 0;
	//};

	//创建对应的接口对象
	virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
        /* [in] */ REFIID riid,
        /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
	{
		if(riid == IID_IStopWatch)
		{
			*ppvObject = static_cast<IStopWatch*>(this);
			return S_OK;
		}
		else if(riid == IID_IUnknown)
		{
			*ppvObject = static_cast<IUnknown*>(this);
			return S_OK;
		}

		*ppvObject = NULL;
		return E_NOINTERFACE;
	};

	//增加引用
    virtual ULONG STDMETHODCALLTYPE AddRef( void) 
	{
		InterlockedIncrement(&m_nRefValue);
		return m_nRefValue;
	};

	//解除引用
    virtual ULONG STDMETHODCALLTYPE Release( void)
	{
		InterlockedDecrement(&m_nRefValue);
		if(m_nRefValue == 0)
			delete this;
		return m_nRefValue;
	};

	virtual HRESULT _stdcall Start()
	{
		BOOL bOK = QueryPerformanceCounter(&m_nStartTime);
		if(!bOK)
			return S_FALSE;
		return S_OK;
	};

	virtual HRESULT _stdcall ElaspedTime(float *elaspedtime)
	{
		LARGE_INTEGER nStopTime;
		BOOL bOK = QueryPerformanceCounter(&nStopTime);
		if(!bOK)
			return S_FALSE;

		*elaspedtime = ((float)(nStopTime.QuadPart - m_nStartTime.QuadPart))/m_nFreq.QuadPart;

		return S_OK;
	};

private:
	LARGE_INTEGER m_nFreq;
	LARGE_INTEGER m_nStartTime;
	volatile unsigned long m_nRefValue;
};

//return IStopWatch interface object
extern "C" HRESULT _stdcall DllGetClassObject(REFCLSID rcsid, REFIID rid, LPVOID* lpvoid)
{
	if(rcsid == CLSID_CStopWatch)
	{
		*lpvoid = static_cast<IStopWatch*>(new CStopWatch);
		return S_OK;
	}
	
	*lpvoid = NULL;
	return CLASS_E_CLASSNOTAVAILABLE;
}



客户端的调用代码

#include "../stopwatch/stopwatcher.h"
#include "../stopwatch/timer_i.h"

#include <iostream>
#include <cstring>
#include <cassert>

#define TIMERDLL L"../Debug/stopwatch.dll"
#define PROCNAME "DllGetClassObject"

typedef HRESULT  (_stdcall*  GETOBJFUNC)(REFCLSID , REFIID , LPVOID* );

using namespace std;
void trace(const char *str)
{
	cout<<str<<endl;
}

void trace(const string& s)
{
	cout<<s.c_str()<<endl;
}

HRESULT CreateInstance(void **p, HMODULE *rhMod)
{
	HMODULE hMod = LoadLibrary(TIMERDLL);
	if(!hMod)
		return E_FAIL;

	GETOBJFUNC proc = 
		(GETOBJFUNC)GetProcAddress(hMod, PROCNAME);

	if(!proc)
		return E_FAIL;

	*p = proc;
	*rhMod = hMod;

	return S_OK;
}

void FreeInstance(HMODULE hMod)
{
	assert(FreeLibrary(hMod));
}

void testInstance()
{
	void *fptr = NULL;
	HMODULE hMod = NULL;
	HRESULT hr = CreateInstance(&fptr, &hMod);
	if(FAILED(hr))
	{
		trace("CreateInstace failed");
		return;
	}

	GETOBJFUNC proc = (GETOBJFUNC)(fptr);
	IUnknown *ptr = NULL;
	
	//首先得到类实例
	//然后根据类实例得到IUnknown
	//最后通过IUnknown调取QueryInterface接口来得到其子类的接口对象
	//调用子类的接口对象
	hr = proc(CLSID_CStopWatch, IID_IUnknown, (LPVOID*)&ptr);
	if(FAILED(hr))
	{
		trace("GetObject failed");
		return;
	}

	if(!ptr)
	{
		trace("ptr is null");
		return;
	}

	IStopWatch *ptrSW = NULL;
	hr = ptr->QueryInterface(IID_IStopWatch, (void**)&ptrSW);
	assert(SUCCEEDED(hr));

	hr = ptrSW->Start();
	assert(SUCCEEDED(hr));

	int m=0;
	for(int i=0; i<10000000; ++i)
		++m;

	float elaspedtime = 0;
	hr = ptrSW->ElaspedTime(&elaspedtime);
	assert(SUCCEEDED(hr));

	cout<<"ElaspedTime:"<<elaspedtime<<endl;

	//释放对象本身
	ptrSW->Release();

	FreeInstance(hMod);
}

int main(int argc, char *argv[])
{
	testInstance();
	getchar();
	return 0;
}



COM组件入门(一),布布扣,bubuko.com

COM组件入门(一)

原文:http://blog.csdn.net/davidsu33/article/details/38539479

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!