Difference between revisions of "Documentation/DevGuide/ProUNO/Bridge/Mapping of Sequence"
m |
(→Multidimensional arrays) |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 12: | Line 12: | ||
==Kinds of arrays== | ==Kinds of arrays== | ||
Arrays in Automation have a particular type. The <code>SAFEARRAY</code>. A <code>SAFEARRAY</code> array is used when a UNO function takes a sequence as an argument. To create a <code>SAFEARRAY</code> in C++, use Windows API functions. The C++ name is also <code>SAFEARRAY</code>, 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: | Arrays in Automation have a particular type. The <code>SAFEARRAY</code>. A <code>SAFEARRAY</code> array is used when a UNO function takes a sequence as an argument. To create a <code>SAFEARRAY</code> in C++, use Windows API functions. The C++ name is also <code>SAFEARRAY</code>, 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: | ||
− | < | + | <syntaxhighlight lang="vb"> |
Dim myarr(9) as String | Dim myarr(9) as String | ||
− | </ | + | </syntaxhighlight> |
JScript is different. It does not have a method to create a <code>SAFEARRAY</code>. Instead, JScript features an <code>Array</code> 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 <code>VBArray</code> object that converts a <code>SAFEARRAY</code> into an <code>Array</code> object, which can then be processed further. | JScript is different. It does not have a method to create a <code>SAFEARRAY</code>. Instead, JScript features an <code>Array</code> 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 <code>VBArray</code> object that converts a <code>SAFEARRAY</code> into an <code>Array</code> object, which can then be processed further. | ||
Line 20: | Line 20: | ||
The Automation bridge accepts both, <code>SAFEARRAY</code> and <code>Array</code> object, for arguments whose UNO type is a sequence. | The Automation bridge accepts both, <code>SAFEARRAY</code> and <code>Array</code> object, for arguments whose UNO type is a sequence. | ||
− | {{ | + | {{Tip|If a <tt>SAFEARRAY</tt> is obtained in JScript as a result of a call to an ActiveX component or a VB Script function (for example, the Internet Explorer allows JScript and VBS code on the same page), then it can also be used as an argument of a UNO function without converting it to an <tt>Array</tt> object.}} |
==Multidimensional arrays== | ==Multidimensional arrays== | ||
Line 26: | Line 26: | ||
To provide an argument for a sequence of sequences, a <code>SAFEARRAY</code> containing <code>VARIANT</code>s of <code>SAFEARRAY</code>s has to be created. For example: | To provide an argument for a sequence of sequences, a <code>SAFEARRAY</code> containing <code>VARIANT</code>s of <code>SAFEARRAY</code>s has to be created. For example: | ||
− | < | + | <syntaxhighlight lang="idl"> |
//UNO method | //UNO method | ||
void foo([in] sequence< sequence< long > > value); | void foo([in] sequence< sequence< long > > value); | ||
− | </ | + | </syntaxhighlight> |
− | < | + | |
+ | <syntaxhighlight lang="vb"> | ||
+ | 'VB | ||
Dim seq(1) As Variant | Dim seq(1) As Variant | ||
Dim ar1(3) As Long | Dim ar1(3) As Long | ||
Line 41: | Line 43: | ||
objUno.foo seq | objUno.foo seq | ||
− | </ | + | </syntaxhighlight> |
The array seq corresponds to the “outer” sequence and contains two <code>VARIANT</code>s, which in turn contain <code>SAFEARRAY</code>s of different lengths. | The array seq corresponds to the “outer” sequence and contains two <code>VARIANT</code>s, which in turn contain <code>SAFEARRAY</code>s of different lengths. | ||
It is also possible to use a multi-dimensional <code>SAFEARRAY</code> if the elements of the sequence are all the same length: | It is also possible to use a multi-dimensional <code>SAFEARRAY</code> if the elements of the sequence are all the same length: | ||
− | < | + | <syntaxhighlight lang="vb"> |
Dim seq(9, 1) As Long | Dim seq(9, 1) As Long | ||
'fill the sequence | 'fill the sequence | ||
... | ... | ||
objUno.foo seq | objUno.foo seq | ||
− | </ | + | </syntaxhighlight> |
Be aware that Visual Basic uses a column-oriented ordering in contrast to C. That is, the C equivalent to the VB array is | Be aware that Visual Basic uses a column-oriented ordering in contrast to C. That is, the C equivalent to the VB array is | ||
− | < | + | <syntaxhighlight lang="c"> |
long seq[2][10] | long seq[2][10] | ||
− | </ | + | </syntaxhighlight> |
The highest dimension in VB is represented by the right-most number. | The highest dimension in VB is represented by the right-most number. | ||
Line 68: | Line 70: | ||
That a returned sequence maps to a <code>SAFEARRAY</code> of <code>VARIANT</code>s 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 <code>SAFEARRAY</code> of <code>VARIANT</code>s containing long values. When the <code>SAFEARRAY</code> is passed in a method as an argument for a parameter of type <code>sequence<long ></code> then it is converted accordingly. However, if the parameter is an <code>any</code>, then the bridge does not have the necessary type information and converts the <code>SAFEARRAY</code> to <code>sequence<any></code>. If the method now expects the any to contain a <code>sequence<long></code> then it may fail. This is confusing if there are pairs of methods like <code>getxxx</code> and <code>setxxx</code>, which take any arguments. Then you may get a <code>SAFEARRAY</code> as a return value, which cannot be used in the respective <code>setXXX</code> call. For example: | That a returned sequence maps to a <code>SAFEARRAY</code> of <code>VARIANT</code>s 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 <code>SAFEARRAY</code> of <code>VARIANT</code>s containing long values. When the <code>SAFEARRAY</code> is passed in a method as an argument for a parameter of type <code>sequence<long ></code> then it is converted accordingly. However, if the parameter is an <code>any</code>, then the bridge does not have the necessary type information and converts the <code>SAFEARRAY</code> to <code>sequence<any></code>. If the method now expects the any to contain a <code>sequence<long></code> then it may fail. This is confusing if there are pairs of methods like <code>getxxx</code> and <code>setxxx</code>, which take any arguments. Then you may get a <code>SAFEARRAY</code> as a return value, which cannot be used in the respective <code>setXXX</code> call. For example: | ||
− | < | + | <syntaxhighlight lang="idl"> |
//UNO IDL | //UNO IDL | ||
any getByIndex(); | any getByIndex(); | ||
void setByIndex([in] any value); | void setByIndex([in] any value); | ||
− | </ | + | </syntaxhighlight> |
− | < | + | |
+ | <syntaxhighlight lang="vb"> | ||
' VB | ' VB | ||
Dim arLong() As Variant | Dim arLong() As Variant | ||
arLong = objUno.getByIndex() 'object returns sequence<long> in any | arLong = objUno.getByIndex() 'object returns sequence<long> in any | ||
objUno.setByIndex arLong 'object receives sequence<any> in any and may cause an error. | objUno.setByIndex arLong 'object receives sequence<any> in any and may cause an error. | ||
− | </ | + | </syntaxhighlight> |
To solve this problem, wrap the argument in a Value Object ([[Documentation/DevGuide/ProUNO/Bridge/Value Objects|Value Objects]]): | To solve this problem, wrap the argument in a Value Object ([[Documentation/DevGuide/ProUNO/Bridge/Value Objects|Value Objects]]): | ||
− | < | + | <syntaxhighlight lang="vb"> |
' VB | ' VB | ||
Dim arLong() As Variant | Dim arLong() As Variant | ||
Line 91: | Line 94: | ||
objUno.setByIndex objValueObject 'object receives sequence<long> | objUno.setByIndex objValueObject 'object receives sequence<long> | ||
− | </ | + | </syntaxhighlight> |
A similar problem may occur when one calls functions of an automation object which takes <code>VARIANT</code>s as arguments and the function expects particular types within those <code>VARIANT</code>s. For example, an automation object expects a <code>VARIANT</code> containing a <code>SAFEARRAY</code> of strings. The bridge only knows from the object's type information that the function expects a <code>VARIANT</code>, but not the contained type. The bridge will therefore do a default conversion of the sequence, which produces a <code>SAFEARRAY</code> of <code>VARIANT</code>s. The function may not be able to understand this argument. Then one can use a value object in order to give the bridge a hint of the expected type. | A similar problem may occur when one calls functions of an automation object which takes <code>VARIANT</code>s as arguments and the function expects particular types within those <code>VARIANT</code>s. For example, an automation object expects a <code>VARIANT</code> containing a <code>SAFEARRAY</code> of strings. The bridge only knows from the object's type information that the function expects a <code>VARIANT</code>, but not the contained type. The bridge will therefore do a default conversion of the sequence, which produces a <code>SAFEARRAY</code> of <code>VARIANT</code>s. The function may not be able to understand this argument. Then one can use a value object in order to give the bridge a hint of the expected type. | ||
If the parameter is a multi–dimensional <code>SAFEARRAY</code>, then 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 <code>SAFEARRAY</code> can be expressed in C as | If the parameter is a multi–dimensional <code>SAFEARRAY</code>, then 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 <code>SAFEARRAY</code> can be expressed in C as | ||
− | < | + | <syntaxhighlight lang="c"> |
long ar[2][10] | long ar[2][10] | ||
− | </ | + | </syntaxhighlight> |
Then the outer sequence must have two elements and each of those sequences has 10 elements. | Then the outer sequence must have two elements and each of those sequences has 10 elements. |
Latest revision as of 15:06, 23 December 2020
Kinds of arrays
Arrays in Automation have a particular type. The SAFEARRAY
. A 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, SAFEARRAY
and Array
object, for arguments whose UNO type is a sequence.
Multidimensional arrays
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 SAFEARRAY
containing VARIANT
s of SAFEARRAY
s has to be created. For example:
//UNO method void foo([in] sequence< sequence< long > > value);
'VB 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 VARIANT
s, which in turn contain SAFEARRAY
s 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
long seq[2][10]
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.
Conversion of returned sequences
Sequences can be returned as return values of uno functions or properties and as in/out or out arguments of uno functions. They are converted into SAFEARRAY
s containing VARIANT
s. If a sequence of sequences is returned, then the VARIANT
s contain again SAFEARRAY
s. For example, if an uno function returns a sequence of strings then the bridge will convert the sequence into a SAFEARRAY
containing VARIANT
s of strings. This is necessary because some languages, for example VBScript can only access members of arrays if they are VARIANT
s.
To process a returned SAFEARRAY
in JScript, use the VBArray
object to convert the SAFEARRAY
into a JScript Array
.
That a returned sequence maps to a SAFEARRAY
of VARIANT
s 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 SAFEARRAY
of VARIANT
s 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 SAFEARRAY
to 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 getxxx
and 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>
A similar problem may occur when one calls functions of an automation object which takes VARIANT
s as arguments and the function expects particular types within those VARIANT
s. For example, an automation object expects a VARIANT
containing a SAFEARRAY
of strings. The bridge only knows from the object's type information that the function expects a VARIANT
, but not the contained type. The bridge will therefore do a default conversion of the sequence, which produces a SAFEARRAY
of VARIANT
s. The function may not be able to understand this argument. Then one can use a value object in order to give the bridge a hint of the expected type.
If the parameter is a multi–dimensional SAFEARRAY
, then 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
long ar[2][10]
Then the outer sequence must have two elements and each of those sequences has 10 elements.
Content on this page is licensed under the Public Documentation License (PDL). |