array.h revision e64031e20c39650a7bc902a3e1aba613b9415dee
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * MS COM / XPCOM Abstraction Layer:
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * Safe array helper class declaration
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * Copyright (C) 2006-2007 Oracle Corporation
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * available from http://www.virtualbox.org. This file is free software;
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * General Public License (GPL) as published by the Free Software
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * The contents of this file may alternatively be used under the terms
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * of the Common Development and Distribution License Version 1.0
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * CDDL are applicable instead of those of the GPL.
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * You may elect to license modified versions of this file under the
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * terms and conditions of either the GPL or the CDDL or both.
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync/** @defgroup grp_COM_arrays COM/XPCOM Arrays
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * The COM/XPCOM array support layer provides a cross-platform way to pass
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * arrays to and from COM interface methods and consists of the com::SafeArray
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * template and a set of ComSafeArray* macros part of which is defined in
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * This layer works with interface attributes and method parameters that have
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * the 'safearray="yes"' attribute in the XIDL definition:
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync <interface name="ISomething" ...>
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync <method name="testArrays">
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync <param name="inArr" type="long" dir="in" safearray="yes"/>
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync <param name="outArr" type="long" dir="out" safearray="yes"/>
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync <param name="retArr" type="long" dir="return" safearray="yes"/>
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync </interface>
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * Methods generated from this and similar definitions are implemented in
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * component classes using the following declarations:
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync STDMETHOD(TestArrays) (ComSafeArrayIn (LONG, aIn),
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync ComSafeArrayOut (LONG, aOut),
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync ComSafeArrayOut (LONG, aRet));
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync * And the following function bodies:
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync STDMETHODIMP Component::TestArrays (ComSafeArrayIn (LONG, aIn),
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync ComSafeArrayOut (LONG, aOut),
50f0e2e83362e100d306a411980d555d46aa00a8vboxsync ComSafeArrayOut (LONG, aRet))
50f0e2e83362e100d306a411980d555d46aa00a8vboxsync if (ComSafeArrayInIsNull (aIn))
54828795a553ed0731f308ebda81675ad2c39d58vboxsync return E_INVALIDARG;
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync if (ComSafeArrayOutIsNull (aOut))
54828795a553ed0731f308ebda81675ad2c39d58vboxsync return E_POINTER;
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync if (ComSafeArrayOutIsNull (aRet))
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync return E_POINTER;
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync // Use SafeArray to access the input array parameter
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync com::SafeArray <LONG> in (ComSafeArrayInArg (aIn));
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync for (size_t i = 0; i < in.size(); ++ i)
50f0e2e83362e100d306a411980d555d46aa00a8vboxsync LogFlow (("*** in[%u]=%d\n", i, in [i]));
50f0e2e83362e100d306a411980d555d46aa00a8vboxsync // Use SafeArray to create the return array (the same technique is used
54828795a553ed0731f308ebda81675ad2c39d58vboxsync // for output array paramters)
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync SafeArray <LONG> ret (in.size() * 2);
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync for (size_t i = 0; i < in.size(); ++ i)
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync ret [i] = in [i];
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync ret [i + in.size()] = in [i] * 10;
b0dfb334954c0552bb583967a3077ec88fd00471vboxsync ret.detachTo (ComSafeArrayOutArg (aRet));
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync return S_OK;
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync * Such methods can be called from the client code using the following pattern:
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync ComPtr <ISomething> component;
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync com::SafeArray <LONG> in (3);
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync in [0] = -1;
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync in [1] = -2;
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync in [2] = -3;
80523be8dba75b5eb32569fd72ddf54f3b009025vboxsync com::SafeArray <LONG> out;
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync com::SafeArray <LONG> ret;
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync HRESULT rc = component->TestArrays (ComSafeArrayAsInParam (in),
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync ComSafeArrayAsOutParam (out),
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync ComSafeArrayAsOutParam (ret));
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync if (SUCCEEDED (rc))
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync for (size_t i = 0; i < ret.size(); ++ i)
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync printf ("*** ret[%u]=%d\n", i, ret [i]);
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync * For interoperability with standard C++ containers, there is a template
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync * constructor that takes such a container as argument and performs a deep copy
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync * of its contents. This can be used in method implementations like this:
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync STDMETHODIMP Component::COMGETTER(Values) (ComSafeArrayOut (int, aValues))
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync // ... assume there is a |std::list <int> mValues| data member
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync com::SafeArray <int> values (mValues);
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync values.detachTo (ComSafeArrayOutArg (aValues));
b60e4b0625949fd68ed97f1353e2174c5b3192e5vboxsync return S_OK;
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync * The current implementation of the SafeArray layer supports all types normally
5d05aa26ae1949e6f0bbc149d8b8e39495710ac7vboxsync * allowed in XIDL as array element types (including 'wstring' and 'uuid').
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync * However, 'pointer-to-...' types (e.g. 'long *', 'wstring *') are not
8d29e9dc0d280b7b26834132b9ce14a3a845a7fdvboxsync * supported and therefore cannot be used as element types.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * Note that for GUID arrays you should use SafeGUIDArray and
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * SafeConstGUIDArray, customized SafeArray<> specializations.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * Also note that in order to pass input BSTR array parameters declared
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * using the ComSafeArrayIn (IN_BSTR, aParam) macro to the SafeArray<>
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * constructor using the ComSafeArrayInArg() macro, you should use IN_BSTR
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * as the SafeArray<> template argument, not just BSTR.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * Arrays of interface pointers are also supported but they require to use a
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * special SafeArray implementation, com::SafeIfacePointer, which takes the
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * interface class name as a template argument (e.g. com::SafeIfacePointer
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * <IUnknown>). This implementation functions identically to com::SafeArray.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * Wraps the given com::SafeArray instance to generate an expression that is
755f4438e1e3a66f23230126b7df46d51006ac24vboxsync * suitable for passing it to functions that take input safearray parameters
755f4438e1e3a66f23230126b7df46d51006ac24vboxsync * declared using the ComSafeArrayIn macro.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * @param aArray com::SafeArray instance to pass as an input parameter.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync (aArray).size(), (aArray).__asInParam_Arr ((aArray).raw())
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * Wraps the given com::SafeArray instance to generate an expression that is
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * suitable for passing it to functions that take output safearray parameters
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * declared using the ComSafeArrayOut macro.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync * @param aArray com::SafeArray instance to pass as an output parameter.
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync (aArray).__asOutParam_Size(), (aArray).__asOutParam_Arr()
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync#else /* defined (VBOX_WITH_XPCOM) */
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync#define ComSafeArrayAsInParam(aArray) (aArray).__asInParam()
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync#define ComSafeArrayAsOutParam(aArray) (aArray).__asOutParam()
64e0c74b525c440a571ce06f3eb6234d75913d76vboxsync#endif /* defined (VBOX_WITH_XPCOM) */
1e2bc03fd1fc133bd3a066b1557471e157df78f6vboxsync////////////////////////////////////////////////////////////////////////////////
1e2bc03fd1fc133bd3a066b1557471e157df78f6vboxsync * Provides various helpers for SafeArray.
1e2bc03fd1fc133bd3a066b1557471e157df78f6vboxsync * @param T Type of array elements.
1e2bc03fd1fc133bd3a066b1557471e157df78f6vboxsync /** Initializes memory for aElem. */
1e2bc03fd1fc133bd3a066b1557471e157df78f6vboxsync /** Initializes memory occupied by aElem. */
1e2bc03fd1fc133bd3a066b1557471e157df78f6vboxsync /** Creates a deep copy of aFrom and stores it in aTo. */
1e2bc03fd1fc133bd3a066b1557471e157df78f6vboxsync static void Copy (const T &aFrom, T &aTo) { aTo = aFrom; }
struct SafeArrayTraits <T *>
template<>
if (aElem)
template<>
if (aElem)
template<>
if (aElem)
if (aFrom)
if (aTo)
struct SafeArrayTraitsBase
return VT_I1;
struct SafeArrayTraits <T *>
template<>
template<>
template<>
template<>
template<>
template<>
void **raw;
SafeArray() {}
#if defined (VBOX_WITH_XPCOM)
m.isWeak = true;
if (arg)
m.isWeak = true;
size_t i = 0;
#if defined (VBOX_WITH_XPCOM)
typedef C <K, T, L, A> Map;
#if defined (VBOX_WITH_XPCOM)
#if defined (VBOX_WITH_XPCOM)
if (m.arr)
return m.size;
if (m.arr)
#if defined (VBOX_WITH_XPCOM)
++ m.size;
T *appendedRaw()
return NULL;
#if defined (VBOX_WITH_XPCOM)
++ m.size;
#if defined (VBOX_WITH_XPCOM)
m.uninit();
T *raw()
#if defined (VBOX_WITH_XPCOM)
return m.arr;
return m.raw;
const T *raw() const
#if defined (VBOX_WITH_XPCOM)
return m.arr;
return m.raw;
#if defined (VBOX_WITH_XPCOM)
#if defined (VBOX_WITH_XPCOM)
* safeArray.cloneTo (ComSafeArrayOutArg (aArg));
#if defined (VBOX_WITH_XPCOM)
#if defined (VBOX_WITH_XPCOM)
m.isWeak = false;
m.size = 0;
if (m.raw)
m.isWeak = false;
return *this;
#if defined (VBOX_WITH_XPCOM)
#if defined (VBOX_WITH_XPCOM)
struct Data
Data()
: isWeak (false)
#if defined (VBOX_WITH_XPCOM)
void uninit()
#if defined (VBOX_WITH_XPCOM)
if (arr)
if (!isWeak)
isWeak = false;
if (arr)
if (raw)
if (!isWeak)
isWeak = false;
#if defined (VBOX_WITH_XPCOM)
T *arr;
T *raw;
Data m;
#if defined (VBOX_WITH_XPCOM)
return *this;
SafeGUIDArray() {}
SafeConstGUIDArray() {}
#if defined (VBOX_WITH_XPCOM)
struct SafeIfaceArrayTraits
if (aElem)
struct SafeIfaceArrayTraits
SafeIfaceArray() {}
#if defined (VBOX_WITH_XPCOM)
if (arg)
m.isWeak = true;
#if defined (VBOX_WITH_XPCOM)
#if defined (VBOX_WITH_XPCOM)
#if defined (VBOX_WITH_XPCOM)
#if defined (VBOX_WITH_XPCOM)