Difference between revisions of "Documentation/DevGuide/ProUNO/Bridge/Mapping of Sequence"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (FINAL VERSION FOR L10N)
m
Line 11: Line 11:
 
{{DISPLAYTITLE:Mapping of Sequence}}
 
{{DISPLAYTITLE:Mapping of Sequence}}
 
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:
 
+
<source lang="vb">
 
   Dim myarr(9) as String
 
   Dim myarr(9) as String
 +
</source>
  
 
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 23: Line 24:
  
 
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:
 
+
<source lang="idl">
 
   //UNO method
 
   //UNO method
 
   void foo([in] sequence< sequence< long > > value);
 
   void foo([in] sequence< sequence< long > > value);
 
+
</source> 
 
+
<source lang="vb"> 
 
   Dim seq(1) As Variant
 
   Dim seq(1) As Variant
 
   Dim ar1(3) As Long
 
   Dim ar1(3) As Long
Line 38: Line 39:
 
    
 
    
 
   objUno.foo seq
 
   objUno.foo seq
 +
</source>
  
 
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:
 
+
<source 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
 +
</source>
  
 
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  
 
+
<source lang="c">
 
   long seq[2][10]
 
   long seq[2][10]
 
+
</source>
 
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 63: Line 66:
  
 
If the parameter is a multi–dimensional <code>SAFEARRAY</code>, 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 <code>SAFEARRAY</code> can be expressed in C as  
 
If the parameter is a multi–dimensional <code>SAFEARRAY</code>, 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 <code>SAFEARRAY</code> can be expressed in C as  
 
+
<source lang="c">
 
   long ar[2][10]
 
   long ar[2][10]
 +
</source>
  
 
Then the outer sequence must have two elements and each of those sequences has 10 elements. 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 any, then the bridge does not have the necessary type information and converts the <code>SAFEARRAY</code> to <code>sequence<any></code>. That is, the called method receives an any containing a <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:
 
Then the outer sequence must have two elements and each of those sequences has 10 elements. 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 any, then the bridge does not have the necessary type information and converts the <code>SAFEARRAY</code> to <code>sequence<any></code>. That is, the called method receives an any containing a <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:
 
+
<source lang="idl">
 
   //UNO IDL
 
   //UNO IDL
 
   any getByIndex();
 
   any getByIndex();
 
   void setByIndex([in] any value);
 
   void setByIndex([in] any value);
 
+
</source>
   'VB
+
<source lang="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.
 +
</source>
  
 
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]]):
 
+
<source 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
Line 88: Line 94:
 
    
 
    
 
   objUno.setByIndex objValueObject 'object receives sequence<long>
 
   objUno.setByIndex objValueObject 'object receives sequence<long>
 
+
</source>
  
 
{{PDL1}}
 
{{PDL1}}
  
 
[[Category:Documentation/Developer's Guide/Professional UNO]]
 
[[Category:Documentation/Developer's Guide/Professional UNO]]

Revision as of 12:51, 22 October 2009



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.

Template:Documentation/Tip

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 VARIANTs of 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

  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.

Returned sequences are converted into SAFEARRAYs containing VARIANTs. If a sequence of sequences is returned, then the VARIANTs contain again SAFEARRAYs.

To process a returned SAFEARRAY in Jscript, use the VBArray object to convert the SAFEARRAY into a JScript Array.

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

  long ar[2][10]

Then the outer sequence must have two elements and each of those sequences has 10 elements. That a returned sequence maps to a SAFEARRAY of 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 SAFEARRAY of 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 SAFEARRAY to 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 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>
Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages