学习之路----COM+

来源:互联网 发布:北方稀土历史交易数据 编辑:程序博客网 时间:2024/04/28 13:44

 模块定义文件

. def文件,

DEF文件是模块定义文件(Module Definition File)。它允许引出符号被化名为不同的引入符号。声明一个函数名,在工程中插入一个Timers.def文件
;Timers.def :Declares the module parameters
LIBRARY  "Timers.DLL"
EXPORTS
  DllGetClassObject  @1 PRIVATE
可能知道,也可以使用 __declspec(dllexport)声明来输出一个函数,但在ATL项目中用
DEF文件。
引出函数的一个简单的方法 _declspec(dllexport),例如:_declspec(dllexport) int MyFunction(int n);
_declspec(dellexport)可用于任何函数,包括类成员函数,他可以告诉编译器将入口放进引入函数表.

//装载DLL。

LoadLibrary() 函数装载动态连接库到应用程序的地址空间。
如果装载成功,侧使用GetProcAddress()得到指向DllGetClassObject() 函数的函数指针。最后使用CreateInstance() 函数就是从Main()中通过 PPV调用。这时DLLGetClassObject()的头两个参数rclsid 和riid并没有被使用,所以传递的是空GUID。

#include "excpt.h"
#include "stdarg.h"
#include <iostream>
using namespace std;
#include "..//Timers//StopWatch.h"
//NOTE:the following line will vary depending on
//where the Timers.dll is located.
#define TIMERSDLL  "..//Timers//Debug//Timers.dll"
typedef HRESULT(_stdcall *DLLGETCLASSOBJECT)(REFCLSID rclsid,REFIID riid,LPVOID *ppv);
//Instantiates a stopwatch object and return it by reference
HRESULT CreateInstance(void** ppv)
{
  HRESULT hr=S_FALSE;
  HINSTANCE hinstDLL;
  DLLGETCLASSOBJECT DllGetClassObject;
  GUID guid;
  hinstDLL=LoadLibrary(TIMERSDLL);//加载动态连接库
  if(hinstDLL==NULL)
  {
   cout<<"unload the TIMESDLL.DLL"<<endl;
  }
  else
  {
   DllGetClassObject=(DLLGETCLASSOBJECT)GetProcAddress(hinstDLL,"DllGetClassObject");//返回指定的动态连接库地址
   if(!DllGetClassObject)
   {
    FreeLibrary(hinstDLL);
          return S_FALSE;
   }
   else
   {
    //call the function
    hr=DllGetClassObject(guid,guid,ppv);
   }  
  }
  return hr;
}

int main(int argc,char*argv[])
{
float nElapsedTime;
HRESULT hr;
IStopWatch *pStopwatch=NULL;
hr=CreateInstance((void**) &pStopwatch);
if(!SUCCEEDED(hr))
{
 cout<<"ERROR:Unable to create Stopwatch!!"<<endl;
}
else
{
// pStopwatch->Start();
 pStopwatch->Start();
 pStopwatch->ElapsedTime(&nElapsedTime);
 cout<<"the overhead time is"
  <<nElapsedTime<<endl;
 pStopwatch->release();
 pStopwatch=NULL;
}
return 0;
}
main()中代码首先调用CreateInstance()获得指向IStopwatch的指针,如果调用成功,就工作。
结束时就把IStopwatch对象就被释放了。调用Release() 将会使STOPWATCH被删除。

 

接口和指针类

接口:接口定义和暴露了组件对象的函数。它是对象提供服务器程序和客户端程序所通过了解服务器程序性能的机制描叙。在c++中接口定义使用一个抽象类创建。IStopwatch定义了CStopwatch类的接口。
组件类:负责实现COM对象的函数,支持一个或多个接口的类。这样CS topwatch是实现IStopwatch的组件类。

在接口的虚函数表中头三个函数指针必须是IUnknown接口的方法。

IUnknown声名:
struct IUnknown
{
  virtual HRESULT _stdcall QueryInterface(REFIID riid,void **ppvobject)=0;
  virtual unsigned long _stdcall AddRef()=0;
  virtual unsigned long _stdcall Release()=;
};
注意:1。IUnknown 返回值不是HRESHULT值。
      2。声明为结构体,不是CLASS
com接口声明时 结构体和类都行。但结构体提供了将他所有的方法缺省的定义成公有函数这一附加优点,接口是被外部调用,所以定义成公有和私有没什么意义。
在定义接口时使用 CLASS  保持了传统C++编码的惯例,也可以使用STRUCT。