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;
}
COM组件入门(一)的更多相关文章
- highcharts图表组件入门教程:如何监听柱状图柱子点击事件动态更新当前数据点数值和所对应X轴刻度
highcharts图表组件入门教程:如何监听柱状图柱子点击事件动态更新当前数据点数值和所对应X轴刻度 作者:highcharts | 时间:2014-6-11 14:07:05 | [小 大] | ...
- Android Navigation 架构组件入门教程
Android Navigation 架构组件入门教程 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:https://www.cnblogs.com/cavalier-/p/1 ...
- Blazor 组件入门指南
翻译自 Waqas Anwar 2021年3月19日的文章 <A Beginner's Guide to Blazor Components> [1] Blazor 应用程序是组件的组合, ...
- JS组件入门
用React感觉component老好用了. 那如何用原生JS来模拟实现React中的component方法呢:http://huziketang.com/blog/posts/detail?post ...
- Android笔记二十七.Service组件入门(一).什么是Service?
转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空) 一.Service 1.Service简单介绍 Service为Android四大组件之中 ...
- es6+react.js组件入门初探
React是一个用于构建用户见面的javascript库. React主要用于构建UI,许多人认为React是MVC中的V(视图) React起源于Facebook的内部项目,用来架设Instagra ...
- bootstrap简单使用布局、栅格系统、modal标签页等常用组件入门
<!DOCTYPE html> <html> <head> <title>bootstrap</title> <!-- 引入boots ...
- 转:ECharts图表组件入门教程之Theme:ECharts图表的皮肤是什么?如何给图表换主题(皮肤)Theme?
一.什么是ECharts图表的皮肤(主题)? 针对这个问题我只能这样回答,ECharts图表的主题(皮肤)就犹如人的衣服一样,是用来衬托和渲染主体,使其变得更加美观好看的目的.你去过ECharts图表 ...
- vux Tabbar组件入门备忘大佬多指点
一.Tabbar引入及使用 1.新创建vue文件 2.在vue文件中添加插件 <template> <div> <tabbar style="position: ...
随机推荐
- hdu 1969(二分)
题意:给了你n个蛋糕,然后分给m+1个人,问每个人所能得到的最大体积的蛋糕,每个人的蛋糕必须是属于同一块蛋糕的! 分析:浮点型二分,二分最后的结果即可,这里要注意圆周率的精度问题! #include& ...
- Android彩蛋效果,微信彩蛋效果
根据Android源码修改,具有微信彩蛋效果 主要代码 public static class Board extends FrameLayout { public static final bool ...
- 【C++】统计代码覆盖率(二)
嗷嗷嗷!!!好激动,我好蠢.不过最后还是解决了.呜呜呜 有些都是东一块西一块查的,如果有侵权欢迎私信我,我注明出处. 一 gcov&CMake 昨天试了下测试代码和被测代码都是c++的情况,直 ...
- js中DOM集合的动态特性
先引出一个问题:通过调用getElements*()这样的方法返回来类(伪)数组,能对其本身的元素进行排序吗? 答案是不能,因为这些对象的都是NodeList . NamedNodeMap 或 HTM ...
- js 判断页面是否加载完成
javascript代码如下: document.onreadystatechange = subSomething; //当页面加载状态改变的时候执行这个方法 function subSomethi ...
- html --- canvas --- javascript --- 在线画板
canvas功能十分强大,制作一个简易画板易如反掌,主要涉及canvas的画线能力,javascript鼠标点击事件 如有问题请参考:http://www.html5party.com/857.htm ...
- Chapter12&Chapter13:程序实例
文本查询程序 要求:程序允许用户在一个给定文件中查询单词.查询结果是单词在文件中出现的次数及所在行的列表.如果一个单词在一行中出现多次,此行只列出一次. 对要求的分析: 1.读入文件,必须记住单词出现 ...
- 50种方法优化SQL Server数据库查询
查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...
- (转载)OC学习篇之---Foundation框架中的其他类(NSNumber,NSDate,NSExcetion)
前一篇说到了Foundation框架中的NSDirctionary类,这一一篇来看一下Foundation的其他常用的类:NSNumber,NSDate,NSException. 注:其实按照Java ...
- Linux下U盘的挂载和文件的拷贝
把文件通过U盘拷贝到linux系统下插好U盘后,查看磁盘情况fdisk -l正常情况下有 Disk /dev/sda:2045 MB,2045247488 bytes47 heads,46 secto ...