序列的映射
Automation 中的数组具有一种特定类型:SAFEARRAY
。当 UNO 函数将序列作为参数时,就要使用 SAFEARRAY
数组。在 C++ 中要创建 SAFEARRAY
,请使用 Windows API 函数。C++ 名称也是 SAFEARRAY
,但在其他语言中,可能以不同的方式命名。例如,在 VB 中,甚至不存在该类型,因为该类型被映射成一个普通的 VB 数组:
Dim myarr(9) as String
JScript 则不同。它没有提供创建 SAFEARRAY
的方法。而是特有 Array
对象,就索引和访问其值而言,该对象可用作普通数组。该对象在内部用一个分发对象表示。JScript 提供 VBArray
对象,该对象将 SAFEARRAY
转换成可以进一步处理的 Array
对象。
UNO 不能识别多维序列。但是,序列的元素也可以是序列。这些“内部”序列的长度可以不同,但是多维数组中维的元素长度都是相同的。
要为序列的序列提供参数,必须创建包含 SAFEARRAY
中 VARIANT
的 SAFEARRAY
。例如:
//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 参数的方法对,如 getxxx
和 setxxx
,这样也会导致混乱。可能会获取 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). |