文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>COM中多个数据值返回

COM中多个数据值返回

时间:2010-10-11  来源:ubunoon

在COM中,实现多个数据返回,可以使用SAFEARRAY和ICollection两种方法,其他方法,我还没有考虑到。

 

使用SAFEARRAY方式返回的多个数据,并不是特别灵活,而且SAFEARRAY在其他语言中,使用也不是特别方便,尤其是JavaScript中,想要处理SAFEARRAY,还是挺麻烦的一件事。同时,SAFEARRAY需要对处理的数据结构进行特别处理,应该算得上是一个麻烦吧。

 

使用ICollection返回多个数据,相对比较方便,当然,也有很多细节需要注意,但是实现了这样一个ICollection对象之后,便可以重用这个对象,相比较SAFEARRAY,重用效果更好,也更容易做更多的数据扩展与数据处理。ICollection是一个枚举容器,需要枚举器来辅助进行操作元素

 

ICollection是标准的COM接口:

 

interface ICollection : IDispatch { [propget, id(DISPID_LISTITEM)] HRESULT Item([in] const VARIANT varIndex, [out, retval] VARIANT *pVal);  [propget, id(DISPID_LISTCOUNT)] HRESULT Count( [out, retval] long *pVal); [propget, id(DISPID_COLLCOUNT)] HRESULT length([out, retval] long *pVal); [propget, id(DISPID_NEWENUM), restricted, hidden]HRESULT _NewEnum([out, retval] IUnknown* *pVal); }; ICollection需要枚举器辅助进行数据处理,非常符合OOP的实现,这些枚举器都用IEnum开头,类似接口为: interface IEnumXXX : IUnknown { HRESULT Next( unsigned long celt, VARIANT * rgvar, unsigned long * pceltFetched); HRESULT Skip(unsigned long celt); HRESULT Reset(); HRESULT Clone(IEnumVARIANT ** ppenum); }; 目前微软已经定义好的IEnumXXX类型有: IEnumFORMATETC, IEnumMoniker, IEnumOLEVERB,IEnumSTATDATA,IEnumSTATSTG,IEnumString,IEnumUnknown,IEnumVARIANT

下面是一个ATL中的ICollection实现:

// idl文件:

 

// DynamicArray.idl : IDL source for DynamicArray.dll
//

// This file will be processed by the MIDL tool to
// produce the type library (DynamicArray.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";
        [
                object,
                uuid(7942687C-3E0D-468B-80E7-7D0FC34B15EF),
                dual,
                helpstring("IVector Interface"),
                pointer_default(unique)
        ]
        interface IVector : IDispatch
        {
                    [id(DISPID_NEWENUM), propget]
                        HRESULT _NewEnum([out, retval] IUnknown** ppUnk);

                        [id(DISPID_VALUE), propget]
                        HRESULT Item(   [in] long Index, 
                                                        [out, retval] VARIANT* pVal);

                        [id(0x00000001), propget]
                        HRESULT Count([out, retval] long * pVal);
        };

[
        uuid(A08196C2-46C7-4BE2-824D-A26581990B43),
        version(1.0),
        helpstring("DynamicArray 1.0 Type Library")
]
library DYNAMICARRAYLib
{
        importlib("stdole32.tlb");
        importlib("stdole2.tlb");

        [
                uuid(38080E8B-9884-49CA-932D-A298E6882598),
                helpstring("Vector Class")
        ]
        coclass Vector
        {
                [default] interface IVector;
        };
};

 

// vector.h文件

 

 

#ifndef __VECTOR_H_
#define __VECTOR_H_

#include "resource.h"       // main symbols

#include <vector>
#include <atlcom.h>

typedef std::vector<VARIANT> CollType;

typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT>, CollType > EnumType;
typedef ICollectionOnSTLImpl<IVector, CollType, VARIANT, _Copy<VARIANT>, EnumType > CollectionType;

/////////////////////////////////////////////////////////////////////////////
// CVector
class ATL_NO_VTABLE CVector : 
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<CVector, &CLSID_Vector>,
        //public IDispatchImpl<IVector, &IID_IVector, &LIBID_DYNAMICARRAYLib>,
        public IDispatchImpl<CollectionType, &IID_IVector, &LIBID_DYNAMICARRAYLib>
        //public CollectionType
{
public:
        CVector()
        {
                m_coll.push_back( CComVariant(100) );
                m_coll.push_back( CComVariant(200) );
                m_coll.push_back( CComVariant(300) );
        }

DECLARE_REGISTRY_RESOURCEID(IDR_VECTOR)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CVector)
        COM_INTERFACE_ENTRY(IVector)
        COM_INTERFACE_ENTRY(IDispatch)
        // COM_INTERFACE_ENTRY(ICollection)
END_COM_MAP()

// IVector
public:

};

 

 

 

 

编译后,注册到系统后。通过OLEView.exe工具查看,可以得到下面的接口信息:

 

 

[
  uuid(7942687C-3E0D-468B-80E7-7D0FC34B15EF),
  helpstring("IVector Interface"),
  dual
]
dispinterface IVector {
    properties:
    methods:
        [id(0xfffffffc), propget]
        IUnknown* _NewEnum();
        [id(00000000), propget]
        VARIANT Item([in] long Index);
        [id(0x00000001), propget]
        long Count();
};

 

显然,我们的ICollection接口实现对象已经ok了。

 

前面已经说过,ICollection实现的枚举容器的接口,在JavaScript中,枚举器使用Enumerator来表示,使用方式如下:

 

 

var enumObj = new Enumerator([collections])
collections 可选,为任意集合对象

 

在JavaScript中枚举器对象具有下面的接口方法:

 

atEnd()    返回一个bool值,指明是否已经到达结尾.如果当前项是集合中的最后一个,或者集合为空,或者当前项没有定义,则返回true,否则返回false  enumObj.atEnd()
item()  返回集合中的当前项 如果没有定义,则返回undefined   enumObj.item()
moveFirst()     指针重新指向集合首位 如果集合集合中没有项,则当前项被设置为defined   enumObj.moveFirst()
moveNext()      将集合中的当前项向下移动一项  enumObj.moveNext()

 

这些接口方法,回自动去调用ICollection中实现的接口函数。因此,我们只需要将ICollection实现对象作为JavaScript中Enumerator对象的参数即可遍历容器中的所有数据。

 

如:

 

   var value = "";
        enumObj = new Enumerator(coll);

        for(; !enumObj.atEnd(); enumObj.moveNext() )
        {
                var x = enumObj.item();
                value += x + "\r\n";
        }

 

在VB中,有直接对枚举类型进行操作的语句,使用FOR ... NEXT方式进行。

 

大部分语言中,对于ICollection中的操作都很方便,因此很容易实现对ICollection对象的实现与处理。

 

ICollection可以作为数组参数进行处理,也可以作为返回值进行返回,在跨语言进行不同的数据处理时,这将是一个很好的多个数据传递粘合剂,并且实现好的枚举器,可以重复使用。

 

myblog:

http://www.cnblogs.com/ubunoon

http://qtrstudio.com/blog

相关阅读 更多 +
排行榜 更多 +
哥布林弹球b服手游下载

哥布林弹球b服手游下载

休闲益智 下载
小马样式盒游戏下载

小马样式盒游戏下载

休闲益智 下载
异变小镇中文版下载安装

异变小镇中文版下载安装

冒险解谜 下载