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



  • 相关阅读:
    Codeforces 845E Fire in the City 线段树
    Codeforces 542D Superhero's Job dp (看题解)
    Codeforces 797F Mice and Holes dp
    Codeforces 408D Parcels dp (看题解)
    Codeforces 464D World of Darkraft
    Codeforces 215E Periodical Numbers 容斥原理
    Codeforces 285E Positions in Permutations dp + 容斥原理
    Codeforces 875E Delivery Club dp
    Codeforces 888F Connecting Vertices 区间dp (看题解)
    Codeforces 946F Fibonacci String Subsequences dp (看题解)
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5368254.html
Copyright © 2011-2022 走看看