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

COM组件入门(一)的更多相关文章

  1. highcharts图表组件入门教程:如何监听柱状图柱子点击事件动态更新当前数据点数值和所对应X轴刻度

    highcharts图表组件入门教程:如何监听柱状图柱子点击事件动态更新当前数据点数值和所对应X轴刻度 作者:highcharts | 时间:2014-6-11 14:07:05 | [小  大] | ...

  2. Android Navigation 架构组件入门教程

    Android Navigation 架构组件入门教程 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:https://www.cnblogs.com/cavalier-/p/1 ...

  3. Blazor 组件入门指南

    翻译自 Waqas Anwar 2021年3月19日的文章 <A Beginner's Guide to Blazor Components> [1] Blazor 应用程序是组件的组合, ...

  4. JS组件入门

    用React感觉component老好用了. 那如何用原生JS来模拟实现React中的component方法呢:http://huziketang.com/blog/posts/detail?post ...

  5. Android笔记二十七.Service组件入门(一).什么是Service?

    转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空) 一.Service 1.Service简单介绍     Service为Android四大组件之中 ...

  6. es6+react.js组件入门初探

    React是一个用于构建用户见面的javascript库. React主要用于构建UI,许多人认为React是MVC中的V(视图) React起源于Facebook的内部项目,用来架设Instagra ...

  7. bootstrap简单使用布局、栅格系统、modal标签页等常用组件入门

    <!DOCTYPE html> <html> <head> <title>bootstrap</title> <!-- 引入boots ...

  8. 转:ECharts图表组件入门教程之Theme:ECharts图表的皮肤是什么?如何给图表换主题(皮肤)Theme?

    一.什么是ECharts图表的皮肤(主题)? 针对这个问题我只能这样回答,ECharts图表的主题(皮肤)就犹如人的衣服一样,是用来衬托和渲染主体,使其变得更加美观好看的目的.你去过ECharts图表 ...

  9. vux Tabbar组件入门备忘大佬多指点

    一.Tabbar引入及使用 1.新创建vue文件 2.在vue文件中添加插件 <template> <div> <tabbar style="position: ...

随机推荐

  1. 怎样预防Ddos攻击

    一.为何要DDOS? 随着Internet互联网络带宽的增加和多种DDOS黑客工具的不断发布,DDOS拒绝服务攻击的实施越来越容易,DDOS攻击事件正在成上升趋势.出于商业竞争.打击报复和网络敲诈等多 ...

  2. Android中垃圾回收日志信息

    原因 GC_CONCURRENTfreed 178K, 41% free 3673K/6151K, external 0K/0K, paused 2ms+2msGC_EXPLICITfreed 6K, ...

  3. selenium python (八)定位frame中的对象

    #!/usr/bin/python# -*- coding: utf-8 -*-__author__ = 'zuoanvip'#在测试过程中经常遇到frame嵌套的应用,加入页面上有A.B两个fram ...

  4. AngularJS自定义指令(Directives)在IE8下的一个坑

    在项目中,由于要兼容到IE8,我使用1.2.8版本的angularJS.这个版本是支持自定义指令的.我打算使用自定义指令将顶部的header从其他页面分离.也就是实现在需要header的页面只用在&l ...

  5. 【HTTP】GET和POST的区别

    [HTTP]GET和POST的区别   HTTP定义了与服务器交互的不同方法,最基本的方法有四种:GET.POST.PUT.DELETE. URL全程是资源描述符,用于描述网上的资源.以上四种方式就是 ...

  6. Floyd算法解决最短路径问题

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的中午,A和B在吃过中饭之后,来到了一个新的鬼屋!鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些 ...

  7. 【quick-cocos2d-x】Lua 语言基础

    版权声明:本文为博主原创文章,转载请注明出处. 使用quick-x开发游戏有两年时间了,quick-x是cocos2d-Lua的一个豪华升级版的框架,使用Lua编程.相比于C++,lua的开发确实快速 ...

  8. Axure中继器基础教程(增行、删当前、标记、全部、规则行) Mark

    ---恢复内容开始--- 一.中继器的新增行 中继器所显示的列表项与中继器的数据集有关,默认情况下是一一对应的.也就是说,中继器数据集中有多少行数据,那么,列表项就有多少个. 那么,我们能不能通过新增 ...

  9. js中location.search、split()HTML5中localStorage

    1. location.search在客户端获取Url参数的方法 location.search是从当前URL的?号开始的字符串 如:http://www.baidu.com/s?wd=baidu&a ...

  10. php和.net 的加密解密

    PHP版: $key = 335ff'; /* * 加密方法 * @param string $input,待加密的字符串 * @param string $key,加密的密码(只能为8位长) * @ ...