COM的知识点小结

转载 2007年10月15日 09:51:00
        1. COM组件的引入方式:
(1)#include “ComComponent.h”
       #include “ComComponent_i.c”
.h头文件中包含组件的声明,_i.c文件中包含接口和嵌套类的GUID声明。
(2)#import "ComComponent.dll" no_namespace rename(…)
#include “#include “ComComponent_i.c”
引入组件的动态库并包含_i.c文件。
2. 组件的创建:(进程内组件)
(1)查询IUnknown接口:
              IUnknown *pIUnknown = NULL;
              HRESULT hr = CoCreateInstance( CLSID_ComComponent , NULL ,
                     CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pIUnknown) ;
得到IUnknown接口后就可以通过QueryInterface()查询其他导出接口。
(2)查询类厂接口:
       3.一些应用实例:
       (1)类层次结构:
       Class Shape
       Class Arc : public Shape
       Class Line : public Shape
       现在要把封装成COM组件的形式调用:
       要明确一点,COM接口是不允许从多于一个接口继承。
       既class IArc : public IShape , public IDispatch是不行的。我们可以这样:
A.      一个组件创建三个接口:分别为IShape , IArc , ILine
B.      为CArc添加基类。有两种方法,一是通过Implement Interface直接添加,二是在CArc声明.h文件中添加:    
public IDispatchImpl<IShape,&IID_IShape, &LIBID_DEMOCTRL2Lib>(后面LIB文件可能不同)。
然后修改:    
COM_INTERFACE_ENTRY2(IDispatch, IArc)
COM_INTERFACE_ENTRY(IShape)
这是因为IArc和IShape 都实现了IDispatch接口,所以在这里要指明在查询IDispatch时返回哪个继承分支。
最后要在idl文件中添加:
coclass Arc
{
        [default] interface IArc; //默认接口
        interface IShape;
};
这种方法可以给任何嵌套类添加基类。
下面给一个实例,附关键代码:
HRESULT hr = CoInitialize(NULL);
        if(FAILED(hr))
        {
               printf("Coinitialize failed! hr=0x%x", hr);
               return 0 ;
        }
        IUnknown *pIUnknown = NULL;
        hr = CoCreateInstance( CLSID_ArcCtrl2 , NULL ,
               CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pIUnknown) ;
        if( FAILED(hr) )
        {
               AfxMessageBox("Can't get IUnknown interface!");
               return 0 ;
        }
        IArcCtrl2 *pIArc = NULL;
        if( pIUnknown!= NULL)
        {
               hr = pIUnknown->QueryInterface(IID_IArcCtrl2, (void **)&pIArc);
               if(FAILED(hr))
               {
                      AfxMessageBox("Can't get IArcCtrl2 interface!") ;
                      return 0 ;
               }
        }
        IShapeCtrl2 *pIShape = NULL;
        pIArc->QueryInterface(IID_IShapeCtrl2, (void **)&pIShape);
        if(pIShape==NULL)
        {
               printf("Cant get IArcCtrl2 interface/n");
               return 0;
        }
        pIShape->TypeId();           //调用了CArcoverride的TypeId()方法
        pIShape->Release();
        pIArc->Release();
        pIUnknown->Release ();
        CoUninitialize();
(2)常常遇到这样的要求,已有组件接口IContainer,现在要在组件基础上加入功能。
但是不采用(1)的方法。
于是可以这样:
在CContainer中声明成员变量:CComPtr<IAddition> m_pAddition;然后在IContainer接口的QueryInterface()方法中暴露IAddition接口。这样的设计很有用,需要在原接口上添加新的接口且不改变原接口提供给用户的接口。
(3).对COM跨线程调用的小测试,我会就这些测试说说我个人的看法,也许会有些问题,欢迎各位指教:
A. 创建一个Simple object,FreeModel1,在Thread Model中选择Single,不选择Free Threaded Marshaler,这样创建的组件支持单线程模型。怎么理解这个单线程模型?我的理解是:组件会自己序列化对组件方法的调用,也就是说可以有多个线程访问组件方法,但是同一时间只有一个,组件会自动处理请求排序。我在测试时有个问题是:组件实例如果在跨线程调用是没有手工列集和散集,我觉得这有点不太好理解了…(手工列集散集需要CoMarshalInterface()和CoUnmarshelInterface())。
B.创建一个Simple object,FreeModel2,在Thread Model中选择Free,不选择Free Threaded Marshaler,这样创建的组件支持多线程模型(MTA)。
C. 与B对应,创建一个Simple object,FreeModel3,在Thread Model中选择Free,并在复选框中Free Threaded Marshaler前打勾,这样的组件支持多线程模型,并在组件内部包含了一个成员变量:CComPtr<IUnknown> m_pUnkMarshaler;组件实例在跨线程调用不须要手工列集和散集。
小结和问题:
问题:组件对象需要跨线程上面三种情况,我都没有手工列集和散集,似乎三中情况下效果是一样的,主线程和子线程同步后都没有问题。
       可以肯定的是,无论是哪种情况,都必须要在主线程和子线程之间同步。测试结果似乎表明:在多线程情况下访问组件对象,客户端自己多线程同步,那么对组件都能正常访问。
代码较多,贴关键部分。感觉一样没结果,哪位有兴趣,希望可以给我点头绪:)。
#define STATUS 1
UINT PrintThread(LPVOID pParam);
// UINT OtherThread(LPVOID pParam);

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
       int nRetCode = 0;

       // initialize MFC and print and error on failure
       if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
       {
              // TODO: change error code to suit your needs
              cerr << _T("Fatal Error: MFC initialization failed") << endl;
              nRetCode = 1;
       }
       else
       {
              // TODO: code your application's behavior here.
              // 初始化
              HRESULT hr = CoInitialize(NULL);
              if(FAILED(hr))
              {
                     AfxMessageBox("Coinitialize failed!");
                     return 0 ;
              }
              IUnknown *pIUnknown = NULL;
              hr = CoCreateInstance( CLSID_FreeModel1 , NULL ,
                     CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pIUnknown) ;
              if( FAILED(hr) )
              {
                     AfxMessageBox("Con't get IUnknown interface!");
                     return 0 ;
              }    
              IFreeModel3 *pIFreeModel3 = NULL; 
              if( pIUnknown!= NULL)
              {
                     hr = pIUnknown->QueryInterface(IID_IFreeModel3, (void **)&pIFreeModel3);
                     if(FAILED(hr))
                     {
                            AfxMessageBox("Can't get IFreeModel3 interface!") ;
                            return 0 ;
                     }
              }
              long Var = 10;
              pIFreeModel3->put_GlobalVar(Var);
              pIFreeModel3->ShowGlobalVar();
              CWinThread *pThread = AfxBeginThread(
                                                                             PrintThread,
                                                                             (void *)pIFreeModel3,
                                                                             0,
                                                                             0,
                                                                             0,
                                                                             NULL );
             WaitForSingleObject(pThread->m_hThread , INFINITE);
              pIUnknown->Release();
              pIFreeModel3->Release();
              printf("STATUS = %d/n",STATUS);
              CoUninitialize();
       }
       return nRetCode;
}
UINT PrintThread(LPVOID pParam)
{
       printf("enter thread PrintThread/n");
       IFreeModel3 *pIFreeModel3 = (IFreeModel3 *)pParam;
       pIFreeModel3->ShowGlobalVar();
       // pIFreeModel3->Release();
       printf("exit thread PrintThread/n");
       return 0;
}
写此文,作为学习总结。
 
 

非常全面的Linux知识点总结

$1 我的Linux需求 Linux博大精深。我只在此讨论一些我对线上Linux机器维护人员的基本需求,比如装机,加硬盘,配网络。只讨论CentOS 6,或者类似的RHEL,当然Ubuntu也可以此...
  • zhouboyu
  • zhouboyu
  • 2016年05月11日 03:15
  • 1470

Android 知识点梳理,较完整

说明:本篇博客只是一个知识整理,因为网上对于Android的知识介绍足够多,因此我不再写相关文章(主要是因为我写的不如人家好),所以所有文章均来自网络,不贴原文章,只提供连接,因此本文旨在减少你对相关...
  • u011240877
  • u011240877
  • 2016年07月26日 13:25
  • 10409

springMVC知识点学习笔记

一、 springMVC开发框架原理图 其中的组件: 1,前端控制器DispatcherServlet(不需要程序员开发) 作用是接收请求,响应结果,相当于转发器 2,处理器映...
  • jaryle
  • jaryle
  • 2016年05月07日 20:36
  • 1315

Struts2知识点小结-非常实用

  • 2010年05月17日 14:49
  • 151KB
  • 下载

C++重要知识点小结---2

C++重要知识点小结---2 C++重要知识点小结--1 :http://www.cnblogs.com/heyonggang/p/3246631.html 1.C++允许程序员声明一个不...
  • lejun2011
  • lejun2011
  • 2013年09月18日 10:08
  • 1066

__attribute__小结,学习C语言你不可放过的知识点

GNU C 的一大特色就是attribute 机制。attribute 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Typ...
  • andrewgithub
  • andrewgithub
  • 2017年12月21日 09:09
  • 67

程序员常见面试之 数据库 知识点小结(二)

前言笔者悉心整理的数据库面试知识点,希望对各位朋友有所帮助。 文章链接 http://blog.csdn.net/never_cxb/article/details/50420521 ,转载请保留出...
  • never_cxb
  • never_cxb
  • 2015年12月24日 21:43
  • 1414

【技术小结1】实习40多天所接触的.NET知识点与心得

今年暑假,找了份关于.NET方面的实习工作。一个月下来,主要是对自己所学的知识进行梳理,同时分享给对于刚入门.NET的新手。希望大家能相互学习。      知识点一:公司的开发框架       对于公...
  • h398085541
  • h398085541
  • 2015年08月19日 16:08
  • 445

android之知识点小结二

SharedPreferences的使用: 在这里也是偏向于使用android自带的SharedPreferences管理机制,简要说明使用流程,备忘: 首先在主activity里面初始化Shared...
  • jason0539
  • jason0539
  • 2013年08月19日 08:40
  • 2707

工作中自己遇到的知识点模糊或者思路堵塞小结(1)

学习surfaceView 1 : setZOrderOnTop(true); mHolder.setFormat(PixelFormat.TRANSPARENT);//设置...
  • qdh186
  • qdh186
  • 2016年07月25日 20:25
  • 243
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:COM的知识点小结
举报原因:
原因补充:

(最多只允许输入30个字)