近期须要用到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. Asp.net 身份验证方式?

    [Forms 身份验证] 通过其可将没有通过身份验证的请求重定向到使用 HTTP 客户端重定向的 HTML 窗体的系统.用户提供凭据并提交该窗体.如果应用程序验证该请求,系统就会发出包含凭据或密钥的 ...

  2. Android项目中单实例数据库类,解决database is locked

    一.数据库操作 package com.ping.db; import android.content.Context; import android.database.sqlite.SQLiteDa ...

  3. Windows执行打开文件命令

    ShellExecute(NULL, "open",  localFile.c_str(),  NULL, NULL, SW_SHOW);          会调用该文件类型关联的 ...

  4. 使用Selenium+appium进行App测试

    1. 启动安卓虚拟机.

  5. ajax给全局变量赋值问题

    ajax给全局变量赋值问题 今天在做项目时,遇到了一个问题.我用的是ajax,要在$.ajax({里面给一个全局变量赋值,结果死活赋值不上,纠结了好半天,后来上网查了查,才知道,ajax默认是异步请求 ...

  6. 在VS2103环境中集成Doxygen工具

    自己已将学习了两三次了吧,差不多这次该总结一下: Doxygen是一种开源跨平台的,以类似JavaDoc风格描述的文档系统,完全支持C.C++.Java.Objective-C和IDL语言,部分支持P ...

  7. 输出(test)

    本题要求从输入的N个整数中查找给定的X.如果找到,输出X的位置(从0开始数):如果没有找到,输出“Not Found”. 输入格式: 输入在第1行中给出2个正整数N(<=20)和X,第2行给出N ...

  8. kerboros安装

    尽管前面尝试了hadoop的simple认证方式,这种方法不是特别安全,在介绍一下hadoop的kerberos方式之前,下面我们尝试一下kerberos. 首先介绍一下Kerboros安装 OS 版 ...

  9. rm 注意

    软连接ln -s lnfile file rm -rf lnfile只是删除lnfile ln -s lndir dir rm -rf lndir 删除链接 rm -rf lndir/删除目录下文件

  10. Hadoop学习记录(1)|伪分布安装

    本文转载自向着梦想奋斗博客 Hadoop是什么? 适合大数据的分布式存储于计算平台 不适用小规模数据 作者:Doug Cutting 受Google三篇论文的启发 Hadoop核心项目 HDFS(Ha ...