序列的映射

From Apache OpenOffice Wiki
Jump to: navigation, search



Automation 中的数组具有一种特定类型:SAFEARRAY。当 UNO 函数将序列作为参数时,就要使用 SAFEARRAY 数组。在 C++ 中要创建 SAFEARRAY,请使用 Windows API 函数。C++ 名称也是 SAFEARRAY,但在其他语言中,可能以不同的方式命名。例如,在 VB 中,甚至不存在该类型,因为该类型被映射成一个普通的 VB 数组:

 Dim myarr(9) as String


JScript 则不同。它没有提供创建 SAFEARRAY 的方法。而是特有 Array 对象,就索引和访问其值而言,该对象可用作普通数组。该对象在内部用一个分发对象表示。JScript 提供 VBArray 对象,该对象将 SAFEARRAY 转换成可以进一步处理的 Array 对象。


Tip.png 对于 UNO 类型为序列的参数,Automation 桥接受 SAFEARRAYArray 对象。在 JScript 中,如果调用 ActiveX 组件或 VB Script 函数(例如,Internet Explorer 允许在同一页上包含 JScript 和 VBS 代码)后得到一个 SAFEARRAY,则无需将其转换为 Array 对象,即可以直接用作 UNO 函数的参数。


UNO 不能识别多维序列。但是,序列的元素也可以是序列。这些“内部”序列的长度可以不同,但是多维数组中维的元素长度都是相同的。


要为序列的序列提供参数,必须创建包含 SAFEARRAYVARIANTSAFEARRAY。例如:

 //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


数组序列与“外部”序列相对应并且包含两个 VARIANT,其中又包含不同长度的 SAFEARRAY

如果序列的元素长度都相同,也可以使用多维 SAFEARRAY:

 Dim seq(9, 1) As Long
 'fill the sequence 
 ...
 objUno.foo seq


请注意:与 C 相比,Visual Basic 使用的是列排序,即 C 语言中相当于 VB 数组的是

 long seq[2][10]

在 VB 中,最高维由最右边的数字表示。


此语言绑定指定“外部”序列与最高维相对应。因此,VB 数组 seq(9,1) 将映射成序列的序列,其中外部序列有两个元素,每个内部序列各有 10 个元素。


返回的序列将转换成包含 VARIANT 的 SAFEARRAY。如果返回包含序列的序列,则 VARIANT 又会包含 SAFEARRAY


要在 Jscript 中处理返回的 SAFEARRAY,请使用 VBArray 对象将 SAFEARRAY 转换成 JScript <cod>Array</code>。当从 UNO 调用 Automation 对象的方法并且参数为 SAFEARRAY 时,将在 UNO 端使用序列。序列的元素类型应按照默认映射与 SAFEARRAY 的元素类型相对应。如果不对应,桥会试图将元素转换成所需的元素类型。


如果参数是一个多维 SAFEARRAY,则都必须提供包含序列的序列。嵌套的序列数与维数相对应。由于维的元素长度相同,因此表示该维的序列长度也应该相同。例如,假定在 C 语言中可以将 SAFEARRAY 表示为

 long ar[2][10]


则外部序列必须有两个元素,其中包含的每个序列有 10 个元素。由于将数组传送回 UNO 时不明确,因此,将返回的序列映射成 VARIANT 中的 SAFEARRAY 并不理想 。但是,桥通过使用 UNO 类型信息,解决了此问题。例如,长整型数的返回序列将导致 VARIANT 中的 SAFEARRAY 包含长整型数值。当在某种方法中将 SAFEARRAY 作为 sequence<long > 类型的参数进行传递时,会对其进行相应的转换。但是,如果参数为 any,则桥就没有必要的类型信息,并且会将 SAFEARRAY 转换成 sequence<any>。也就是说,调用的方法接收到的 any 将包含 sequence<any>。如果现在方法希望 any 包含 sequence<long>,则可能会失败。如果存在接受 any 参数的方法对,如 getxxxsetxxx,这样也会导致混乱。可能会获取 SAFEARRAY 作为返回值,但是在相应的 setXXX 调用中无法使用该值。例如:

 //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.


为解决此问题,需要将在值对象中包装参数 (专业 UNO - UNO 语言绑定 - Automation 桥 - 类型映射 - 值对象):

 '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