zoukankan      html  css  js  c++  java
  • COM应用总结(1/3)

    很久没有涉及COM组件的内容了,这两天有个已有的产品需要更新涉及了COM的处理,小组人员对这个不是很熟悉,给小组人员交流了一下,把主要的内容记录一下,对于快速理解和上手提供一些指导,当然对于具体的工作原理和更多的内容参考具体的图书进行学习。

    初步分三篇总结一下:

    Ø C++中的COM组件

    Ø C#中的COM组件

    Ø C++实例和部署

    基础和参考资料

    All-In-One Code Framework http://cfx.codeplex.com/ 这个项目中有使用C# C++建立一个COM组件[DLL EXE]等的详细步骤。

    COM本质论和 潘爱民编写的COM原理和应用 是非常出色的参考书籍

    C++中的COM组件

    以一个例子进行说明

    COM组件

    建立一个最简单的形式说明,这个组件接口名称为IMyKit ,方法就一个DoWork,参数一个传入,一个传出,具体如下

    interface IMyKit : IDispatch{
    [id(1)] HRESULT DoWork([in] BSTR text, [out] BSTR* msg);
    };
    [
    uuid(87BF6309-28B6-40FA-AD26-5175D884D28E),
    version(1.0),
    ]
    library ComPlugLib
    {
    importlib("stdole2.tlb");
    [
    uuid(D7D0B2E8-1795-4E23-96BF-F07EC28FB44C)
    ]
    coclass MyKit
    {
    [default] interface IMyKit;
    };
    };

    STDMETHODIMP CMyKit::DoWork(BSTR text, BSTR* msg)
    {
           AFX_MANAGE_STATE(AfxGetStaticModuleState());
           CString t = text;
           AfxMessageBox(t);
           CString r = _T("out text");
           *msg = r.AllocSysString();
           return S_OK;
    }
    C++使用以上组件的方法

    首先引入定义

    #ifdef _DEBUG

    #import "../Debug/ComPlug.dll" no_namespace raw_interfaces_only

    #else

    #import "../Release/ComPlug.dll" no_namespace raw_interfaces_only

    #endif

    初始化

    // 必须调用这个初始化
    CoInitialize (NULL);

    /*COM组件参数有:in out/ret几种,空间分配原则:
    in: 调用者负责申请和释放
    out:COM组件负责申请,调用者负责释放
    违反上述原则会出现内存泄漏
    */

    使用形式1

    在纯WIN32项目用,其他偶尔用

    HRESULT hr;
    ///纯Win32应用时的方法
    IMyKit* pKit;
    hr = ::CoCreateInstance (__uuidof(MyKit),NULL,CLSCTX_INPROC_SERVER, __uuidof(IMyKit),(void**)&pKit);
    if(SUCCEEDED(hr))
    {
    BSTR t = ::SysAllocString(L"hello");
    BSTR r;
    pKit->DoWork(t, &r);
    MessageBoxW(NULL, r, NULL, MB_OK);
    ///字符串的转换支持,同类有一系列函数,空间分配在栈上,不要释放
    USES_CONVERSION;
    LPSTR p = W2A(r);
    MessageBoxA(NULL, p, NULL, MB_OK);
    ::SysFreeString(t);
    ::SysFreeString(r);
    pKit->Release();
    pKit = NULL;
    }

    使用形式2

    常用

    //和MFC、ATL库结合起来使用,这个是最常用的情况
    //还用一类comutil.h中_bstr_t 的封装
    IMyKitPtr kit;
    hr = kit.CreateInstance(__uuidof(MyKit));
    if(SUCCEEDED(hr))
    {
    /*COM中的基本类型如VARIANT比较复杂,一般情况下不要直接使用
    常用的几个变量 简化COM类型的Variant的调用 COleSafeArray COleVariant CComBSTR
    */
    COleVariant vTrue=COleVariant((short)true),
    vFalse=COleVariant((short)false),
    vOpt=COleVariant((long)DISP_E_PARAMNOTFOUND, VT_ERROR),
    vNull=(COleVariant)(_T("")),
    vOne=COleVariant((short)1);
    CComBSTR text, msg;
    text = _T("in text");
    kit->DoWork(text, &msg);
    CString str =msg;
    AfxMessageBox(str);
    kit = NULL;
    }

    使用形式3

    有些复杂,不太常用

    ///动态调用
    CComPtr<IDispatch> pCF;
    CLSID clsid;
    const LPOLESTR guid = L"{D7D0B2E8-1795-4E23-96BF-F07EC28FB44C}"; 
    CLSIDFromString(guid, &clsid);
    HRESULT result = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IDispatch, (void**)&pCF);
    if (result== S_OK)
    {
    DISPPARAMS dispparams; 
    memset(&dispparams, 0, sizeof dispparams);
    dispparams.cArgs = 2;
    dispparams.cNamedArgs = 0;
    VARIANTARG* pvarg = new VARIANTARG[dispparams.cArgs];
    dispparams.rgvarg = pvarg;
    memset(pvarg, 0, sizeof(VARIANTARG) * dispparams.cArgs);
    CComBSTR t="dynamic", r;
    //和函数的声明相反的顺序
    pvarg[0].vt = VT_BSTR|VT_BYREF;
    pvarg[0].pbstrVal = &r;
    pvarg[1].vt = VT_BSTR;
    pvarg[1].bstrVal = t;
    DISPID id = 1;//函数的标号
    result = pCF->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
    for(UINT i=0; i< dispparams.cArgs; i++)
    {
    VariantClear(&dispparams.rgvarg[i]);
    }
    delete []pvarg;

    结束

    CoUninitialize();
  • 相关阅读:
    [学习笔记] 网络最大流的HLPP算法
    [学习笔记] LCT 初步
    js中函数的原型及继承
    关于js中函数的一点总结
    关于css实现水平及垂直居中的方法记录
    js基础总结03 --操作数组
    近期学习es6后对变量提升及let和const的一点思考
    用css和js实现侧边菜单栏点击和鼠标滑动特效
    用css或js实现文本输入框的特效
    Jmeter怎样打印日志
  • 原文地址:https://www.cnblogs.com/2018/p/1799321.html
Copyright © 2011-2022 走看看