Variant array element -> class object (or com server) paramaray function= pointer, not value?

L

Lee Benfield

(x posted, as I'm working with excel 97, but this exibits on VB6)

When you pass an element of a variant array to a class function
(and ONLY a class function, non class function and class subs do not
exhibit this), you end up with something which looks suspiciously
like a pointer instead of the correct value. Is there a relevant KB
article for this? (can't find one).

Note that this requires at least 2 values in the paramarray.

Can anyone point me at either a fix or an explanation?

Example:
Private Sub showbug()
Dim ca As clsA
Set ca = New clsA

Dim v
v = Array(1, 2, 3, 4)
Call ca.testSub(v(0), v(1), v(2), v(3))
Call ca.testFn(v(0), v(1), v(2), v(3))
call ca.testFn(v(2))
End Sub
clsA:==========
Public Sub testSub(ParamArray foo() As Variant)
Debug.Print Join(foo, ",")
End Sub

Public Function testFn(ParamArray foo() As Variant) As Variant
Debug.Print Join(foo, ",")
testFn = "Oops"
End Function
<<==============

Output:

1,2,3,4
1556816,1556832,1556848,1556864

(note the incrementing addresses - swap array elements for predictable
behaviour!)

I've tested that this also exhibits when passing to a com server,
([vararg] [in] SAFEARRAY(VARIANT) *, [out, retval] VARIANT *)
incorrect elements end up as VT_I4 regardless of input type.

At my wits end!

Thanks.

Lee.
 
K

Ken Halter

Lee said:
(x posted, as I'm working with excel 97, but this exibits on VB6)

When you pass an element of a variant array to a class function
(and ONLY a class function, non class function and class subs do not
exhibit this), you end up with something which looks suspiciously
like a pointer instead of the correct value. Is there a relevant KB
article for this? (can't find one).

Note that this requires at least 2 values in the paramarray.

Can anyone point me at either a fix or an explanation?

That is pretty strange. Note that the same thing happens when passed to
a Form (which is nothing more than a specialized class)

This code works from anywhere. It doesn't use ParamArray though.
'==============Module
Option Explicit

Public Sub Main()
Dim ca As clsA
Set ca = New clsA

Dim v
v = Array(1, 2, 3, 4)
Call ca.testSub(v)
Call ca.testFn(v)
Call ca.testFn(v(2))
End Sub
'==============clsA
Option Explicit

Public Sub testSub(Param As Variant)
If IsArray(Param) Then
Debug.Print Join(Param, ",")
Else
Debug.Print Param
End If
End Sub

Public Function testFn(Param As Variant) As Variant
If IsArray(Param) Then
Debug.Print Join(Param, ",")
testFn = "Oops"
Else
Debug.Print Param
End If
End Function
'==============
 
P

Pásztor, Zoltán

Lee said:
(x posted, as I'm working with excel 97, but this exibits on VB6)

When you pass an element of a variant array to a class function
(and ONLY a class function, non class function and class subs do not
exhibit this), you end up with something which looks suspiciously
like a pointer instead of the correct value. Is there a relevant KB
article for this? (can't find one).

Note that this requires at least 2 values in the paramarray.

Can anyone point me at either a fix or an explanation?

<snip>

Seems a real bug. Some playing around with your code indicates clearly that
in these special circumstances the argument type is filled incorrectly by
the call sequence as 'Long' instead of 'Reference to Variant' (which would
be shown as the contained type by both TypeName and VarType).

This hypothesis is also confirmed by the fact that the output value cannot
be retrieved by the caller.

Here's the modified code:

' (module): ==================
Public Sub showbug()
Dim ca As clsA

Set ca = New clsA

Dim v As Variant
Dim v2 As Variant

' v = Array(1, 2, 3, 4)

' Dim aT() As String
' ReDim aT(0 To 3)
' v = aT
v = Split("A B C D", " ")
v2 = 13

Call ca.testSub(v(0), v(1))
Call ca.testFn(9, v(1), v2)
Debug.Print "After: "; v(1); v2
Call ca.testFn(v(1))
Debug.Print "After: "; v(1)

' Call ca.testSub(v(0), v(1), v(2), v(3))
' Call ca.testFn(v(0), v(1), v(2), v(3))
' Call ca.testFn(v(2))
End Sub

' (clsA): =========
Public Sub testSub(ParamArray foo() As Variant)
Dim UB As Long

UB = UBound(foo)
Debug.Print "Sub, UB: "; UB,
Debug.Print Join(foo, ",")
End Sub

Public Function testFn(ParamArray foo() As Variant) As Variant
Dim UB As Long
Dim i As Long

UB = UBound(foo)
Debug.Print "Fun, UB:"; UB,
Debug.Print Join(foo, ",")
For i = 0 To UB
Debug.Print VarType(foo(i)), TypeName(foo(i)), foo(i)
foo(i) = 100 + i
Next i
End Function
'=====================

And the output is:

ShowBug
Sub, UB: 1 A,B
Fun, UB: 2 9,1242896,13
2 Integer 9
3 Long 1242896
2 Integer 13
After: B 102 <=== *Note*: B should've changed to 101
Fun, UB: 0 B
8 String B
After: 100

Thanx for pointing this out.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top