To return multiple data in COM, you can use the safearray and icollection methods. I have not considered other methods.
Multiple data returned using safearray is not very flexible, and safearray is not very convenient in other languages, especially in Javascript, to process safearray, it is still a very troublesome thing. At the same time, safearray needs to specially process the data structure to be processed, which should be considered a hassle.
It is relatively convenient to return multiple data using icollection. Of course, you need to pay attention to many details. But after such an icollection object is implemented, You can reuse this object, the reuse effect is better, and more data expansion and data processing are easier. Icollection is an enumeration container that requires an enumerator to help you operate elements.
Icollection is a standard COM interface:
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 requires an enumerator to assist in data processing, it is very compatible with OOP implementation. These enumerators start with ienum. Similar interfaces are: interface ienumxxx: iunknown {hresult next (unsigned long Celt, variant * rgvar, unsigned long * pceltfetched ); hresult SKIP (unsigned long CELT); hresult reset (); hresult clone (ienumvariant ** ppenum) ;}; currently, Microsoft has defined the following types of ienumxxx:
Ienumformatetc,Ienummoniker,Ienumoleverb,Ienumstatdata,Ienumstatstg,Ienumstring,Ienumunknown,Ienumvariant
The icollection implementation in ATL is as follows:
// IDL file:
// Dynamicarray. IDL: IDL source for dynamicarray. DLL // This file will be processed by the midl tool to // produce the Type Library (dynamicarray. TLB) and handle alling code. import "oaidl. IDL "; import" ocidl. IDL "; [object, UUID (UID), 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 (UID ), helpstring ("Vector class")] coclass vector {[Default] interface ivector ;};};
// Vector. h file
# 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 extends <ivector, colltype, variant, _ copy <variant>, enumtype> collectiontype; //////////////////////////////////////// /// // cvectorclass atl_no_vtable cvector: public role <strong>, public ccomcoclass <cvector, & clsid_vector>, // public idispatchimpl <ivector, & iid_ivector, & strong>, public idispatchimpl <collectiontype, & iid_ivector, & lt; // public collectiontype {public: cvector () {m_coll.push_back (ccomvariant (100); m_coll.push_back (ccomvariant (200); m_coll.push_back (ccomvariant (300 ));} construct (idr_vector) construct () begin_com_map (cvector) com_interface_entry (ivector) com_interface_entry (idispatch) // com_interface_entry (icollection) end_com_map () // ivectorpublic :};
After compilation, register it to the system. You can view the following interface information through oleview.exe:
[UUID (UID), helpstring ("ivector interface"), dual] dispinterface ivector {properties: Methods: [ID (0 xfffffffc), propget] iunknown * _ newenum (); [ID (00000000), propget] variant item ([in] Long index); [ID (0x00000001), propget] Long Count ();};
Obviously, our icollection interface implementation object is OK.
As mentioned above, the icollection container enumeration interface is represented by enumerator in Javascript. The usage is as follows:
VaR enumobj = new enumerator ([collections]) collections (optional) Any set object
In JavaScript, the enumerator object has the following interface methods:
Atend () returns a bool value indicating whether it has reached the end. if the current item is the last one in the Set, the set is empty, or the current item is not defined, true is returned; otherwise, falseenumobj is returned. atend () item () returns the current item in the set. If it is not defined, undefinedenumobj is returned. the item () movefirst () Pointer Points to the first place of the set. If no item exists in the Set, the current item is set to definedenumobj. movefirst () movenext () moves the current item in the set down an enumobj. movenext ()
These interface methods automatically call the interface functions implemented in icollection. Therefore, we only need to use the icollection implementation object as the parameter of the enumerator object in JavaScript to traverse all the data in the container.
For example:
VaR value = "";
Enumobj = new enumerator (Coll); (;! Enumobj. atend (); enumobj. movenext () {var x = enumobj. Item (); Value + = x + "\ r \ n ";}
In VB, there are statements that operate on enumeration types directly, using the for... next method.
In most languages, operations in icollection are convenient, so it is easy to implement and process icollection objects.
Icollection can be processed as array parameters or returned as return values. When different data processing methods are performed across languages, this is a good way to use multiple data transmission adhesives, and the implemented enumerator can be reused.
Myblog:
Http://www.cnblogs.com/ubunoon
Http://qtrstudio.com/blog