atl

后邦定
VB中后邦定
 dim objMath as Object
 Dim nResult as Integer
 Set objMath =CreateObject("Chapter6.Math")
 nResult=objMath.Add(100,55)
 Set objMath=Nothing
在Visual Basic 中,Object类型保存了一个IDispatch指针,且CreateObject例程可以创建一个有ProgID指定的组件的实例
c++中中后邦定
 CLSIDFromProgID("Chapter6.Math",&clsid);
 IDispatch pDispatch=0;
 CoCreateInstance(clsid,
                  ...
                  IID_IDispatch,
                  (void**)&pDispatch);
  DISPID dispid;
  pDispatch->GetIDsOfNames("Add",&dispid);//将add映射为dispid
  pDispatch->Invoke(dispid,parameters,&result,...);//dispid被映射为派发表中一个确切的偏移量,用来确定哪个接口方法被调用
  pDispatch->Release();
实现IDispatch接口
   如果一个接口通过IDispatch接口向外公开它的功能,则它被看作一个automation component(自动化组件)
   只实现IDispatch接口的组件只能提供派发接口
  
   声明一个派发接口
   [
    uuid(0D17C2EA-0D1B-49B8-8D0E-23AE05F14FA8),
    helpstring("DMath dispointerface")
   ]
   dispionterface DMath
   {
    properties:
     methods:
     [id(1)] long Add(long lOp1,lOp2);
   };
   ....
   coclass Math
   {
    [default] dispionterface DMath;
   };
   可以用IDL来描述相同的接口
   [
     object,
     uuid(0D17C2EA-0D1B-49B8-8D0E-23AE05F14FA8),
     helpstring("IMath Idispointerface")")
   ] 
   interface IMath : IDispatch
   {
      [id(1), helpstring("method Add")] HRESULT Add([in] VARIANT varOp1,[in] VARIANT varOp2,[out,retval] ARIANT* pvarResult) ;
   };
   ....
   coclass Math
   {
    [default] interface IMath;
   };

访问基于IDispatch的接口
  对于派发接口或双向接口的客户程序,有许多选项涉及它如何邦定到一个自动化组件的功能。
  如果组件只实现派发接口,并且不提供类型库,后邦定是唯一的选项
  如果组件实现派发接口,并且提供类型库,组件可以选择后邦定和被称为ID的邦定
  如果组件实现双向接口,并且提供类型库,组件可以选择后邦定,ID的邦定和前邦定之间选择
 
后邦定(动态邦定)
  客户机程序在运行时决定组件的功能
  客户机程序的开发阶段并不对方法的名字和参数类型进行检查,相反,组件的功能只有在运行时才被申请并调用
  也就是说,客户机程序首查询DISPID的方法,然后构造DISPPARAMS结构,接着通过IDispatch接口调用Invoke方法
  工作量大,灵活性高,如果服务器接口发生变化,则客户机程序不用重新编译就可以从服务器接口的新增特性中受益
    
  VB中的后邦定例子
 Dim objMath as Object
 Dim nResult as Integer
 Set objMath =CreateObject("Chapter6.Math")
 nResult=objMath.Add(100,55)
 Set objMath=Nothing
  
  c++中的后邦定例子                            
 IDispatch *pDispatch;
 HRESULT hr=CoCreateInstance(CLSID_Math,
                  NULL,
                  CLSCTX_SERVER,
                  IID_IDispatch,
                  (void**)&pDispatch);

  if(FAILED(hr))
  {..}
  LPOLESTR lpOleStr=L"Add";
  DISPID dispid;
  hr=pDispatch->GetIDsOfNames(IID_NULL,
                               &lpOleStr,
                               1,
                               LOCALE_SYSTEM_DEFAULT,
                               &dispid);//将add映射为dispid
  if(FAILED(hr))
  {...}
  DISPPARAMS dispparms;
  memset(&dispparms,0,sizeof(DISPPARAMS));
  dispparms.cArgs=2;
  
  VARIANTARG* pArg=new VARIANTARG[dispparms.cArgs];
  dispparms.rgvarg=pArg;
  memset(&pArg,0,sizeof(VARIANT)*dispparms.cArgs);
   dispparms.rgvarg[0].vt=VT_I4;
   dispparms.rgvarg[0].lVal=55;
   dispparms.rgvarg[1].vt=VT_I4;
   dispparms.rgvarg[1].lVal=100;

   VARIANTARG varResult;
   VariantInit(&varResult);
   hr=pDispatch->Invoke(dispid,
                        IID_NULL,
                        LOCALE_SYSTEM_DEFAULT,
                        DISPATCH_METHOD,
                        &dispparms,
                        &varResult,
                        0,NULL);
 

//备注:
   typedef struct tagDISPPARAMS
   {
      VARIANTARG* rgvarg;
      DISPID*     rgdispidNamedArgs;
      UINT        cArgs;
      UINT        cNameArgs;
   }DISPPARAMS;

ID邦定(前邦定)
    他提高了性能,并且在编译时进行类型检查
    在Visual Basic开发工具中,选择"Visual Basic References"选项添加类型信息
    当编译你的工程时,Visual Basic编译器将根据组件中的类型信息检查代码的语法和参数类型,另外,Visual Basic为每个方法
    和属性缓存一个DISPID 这就避免了在运行时需检查每一个成员的DISPID
    当一个接口改变时,需对组件重新编译
ID邦定例子
  Visual Basic
   Dim objMath as New Chapter6_Server.Math
   Dim nResult as Integer
   nResult=objMath.Add(55,100)

C++ID邦定
  Class Wizard class..->From TypeLib选项 他将自动化组件产生一个包装类
  该包装类提供ID邦定,DISPID的值是在源文件中硬性指定的 支持编译时类型检查
前邦定的需求信息
   需要组件提供一定的类型信息,并且要求组件实现一个双向接

你可能感兴趣的:(atl)