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: ...
随机推荐
- Yii系列教程(四):使用Memcache保存会话
1环境准备 安装Memcached服务端: yum -y installmemcached.x86_64 安装PHP-Memcache扩展: yum -y installphp-pecl-memcac ...
- Garlands
题意: n个数分成m段,每段偶数个数,最小化和最大段的半个区间的数字和. 分析: 先想到了二分,dp求能分成的最小段数. #include <map> #include <set&g ...
- selenium python (四)键盘事件
#!/usr/bin/python# -*- coding: utf-8 -*-__author__ = 'zuoanvip' #在实际测试过程中,有时候我们需要使用tab键将焦点转移到下一个需要操作 ...
- nodejs ctrl+B 快捷键设置
开发 nodejs 的时候,要使用 sublime 软件,其中的启动方式有很多中.可以通过 supersivor 当然也可以 利用nodejs 的自身功能通过 ctrl+B来直接启动. 具体设置方式, ...
- bzoj1391 最大权闭合子图(also最小割、网络流)
一道裸的最小割的题,写一下只是练练手. 表示被卡M,RE不开心.一道裸题至于吗? 再次复习一下最大权闭合子图: 1.每一个点若为正权,与源点连一条容量为绝对值权值的边.否则连向汇点一条容量为绝对值权值 ...
- UDP模式与TCP模式的区别
1.TCP有连接状态,而UDP没有. 2.TCP应用层使用无需考虑包的大小及发送情况,而UDP需要. 3.TCP中IP包大小的决定者是Socket,而UDP为应用层.
- kerboros安装
尽管前面尝试了hadoop的simple认证方式,这种方法不是特别安全,在介绍一下hadoop的kerberos方式之前,下面我们尝试一下kerberos. 首先介绍一下Kerboros安装 OS 版 ...
- adb device出现error:unknown host service
最近在windows下使用adb device时,提示“ADB server didn't ACK” & “error: unknown host service”错误. 网上搜索了下,是说a ...
- iis 支持html执行php输出
iis 支持html执行php输出 2012-07-25 10:50:23| 分类: PHP|举报|字号 订阅 在HTML中有个简单的的PHP随机数需要输出,例如: <td backg ...
- linux 分区与挂载
流程:分区-格式化-挂载 1.添加硬盘 使用fdisk -l命令查看磁盘状态 此处可以看到两块硬盘sda和sdb,第一块硬盘sda是装好系统的.sdb硬盘是未进行分区的. 本例将这个20G的硬盘分区, ...