Mapping of Sequence
Arrays in Automation have a particular type. The
SAFEARRAY array is used when a UNO function takes a sequence as an argument. To create a
SAFEARRAY in C++, use Windows API functions. The C++ name is also
SAFEARRAY, but in other languages it might be named differently. In VB for example, the type does not even exist, because it is mapped to an ordinary VB array:
Dim myarr(9) as String
JScript is different. It does not have a method to create a
SAFEARRAY. Instead, JScript features an
Array object that can be used as a common array in terms of indexing and accessing its values. It is represented by a dispatch object internally. JScript offers a
VBArray object that converts a
SAFEARRAY into an
Array object, which can then be processed further.
The Automation bridge accepts both,
Array object, for arguments whose UNO type is a sequence.
UNO does not recognize multi-dimensional sequences. Instead, a sequences can have elements that are also sequences. Those “inner” sequences can have different lengths, whereas the elements of a dimension of a multi-dimensional array are all the same length.
To provide an argument for a sequence of sequences, a
SAFEARRAYs has to be created. For example:
//UNO method void foo([in] sequence< sequence< long > > value);
Dim seq(1) As Variant Dim ar1(3) As Long Dim ar2(4) As Long 'fill ar1, ar2 ... seq(0) = ar1 seq(1) = ar2 objUno.foo seq
The array seq corresponds to the “outer” sequence and contains two
VARIANTs, which in turn contain
SAFEARRAYs of different lengths.
It is also possible to use a multi-dimensional
SAFEARRAY if the elements of the sequence are all the same length:
Dim seq(9, 1) As Long 'fill the sequence ... objUno.foo seq
Be aware that Visual Basic uses a column-oriented ordering in contrast to C. That is, the C equivalent to the VB array is
The highest dimension in VB is represented by the right-most number.
This language binding specifies that the “outer” sequence corresponds to the highest dimension. Therefore, the VB array seq(9,1) would map to a sequence of sequences where the outer sequence has two elements and the inner sequences each have ten elements.
Returned sequences are converted into
VARIANTs. If a sequence of sequences is returned, then the
VARIANTs contain again
To process a returned
SAFEARRAY in Jscript, use the
VBArray object to convert the
SAFEARRAY into a JScript
When a method of an Automation object is called from UNO and a parameter is a
SAFEARRAY, then a sequence is used on the UNO side. The element type of the sequence should correspond to the element type of the
SAFEARRAY according to the default mapping. If it does not, the bridge tries to convert the elements into the expected element type.
If the parameter is a multi–dimensional
SAFEARRAY, then one has to provide a sequence containing sequences has to be provided. The number of nested sequences corresponds to the number of dimensions. Since the elements of a dimension have the same length, the sequences that represent that dimension should also have the same length. For example, assume the expected
SAFEARRAY can be expressed in C as
Then the outer sequence must have two elements and each of those sequences has 10 elements. That a returned sequence maps to a
VARIANTs is not ideal because it is ambiguous when the array is passed back to UNO. However, the bridge solves this problem by using UNO type information. For example, a returned sequence of longs will result in a
VARIANTs containing long values. When the
SAFEARRAY is passed in a method as an argument for a parameter of type
sequence<long > then it is converted accordingly. However, if the parameter is an any, then the bridge does not have the necessary type information and converts the
sequence<any>. That is, the called method receives an any containing a
sequence<any>. If the method now expects the any to contain a
sequence<long> then it may fail. This is confusing if there are pairs of methods like
setxxx, which take any arguments. Then you may get a
SAFEARRAY as a return value, which cannot be used in the respective
setXXX call. For example:
//UNO IDL any getByIndex(); void setByIndex([in] any value);
' VB Dim arLong() As Variant arLong = objUno.getByIndex() 'object returns sequence<long> in any objUno.setByIndex arLong 'object receives sequence<any> in any and may cause an error.
To solve this problem, wrap the argument in a Value Object (Value Objects):
' VB Dim arLong() As Variant arLong = objUno.getByIndex() 'object returns sequence<long> in any Dim objValueObject As Object Set objValueObject = objServiceManager.Bridge_GetValueObject() objValueObject.set “long”, arLong objUno.setByIndex objValueObject 'object receives sequence<long>
|Content on this page is licensed under the Public Documentation License (PDL).|