zoukankan      html  css  js  c++  java
  • COM组件入门(一)

    近期须要用到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;
    }
    



    client的调用代码

    #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;
    }
    



  • 相关阅读:
    最大子数组1
    大道至简阅读笔记03
    I-think-3
    第3周学习进度
    大道至简阅读笔记02
    四则运算题3
    大道至简阅读笔记01
    第2周学习进度
    构建之法阅读笔记03
    按Right-BICEP的测试用例
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5368254.html
Copyright © 2011-2022 走看看