The Issue: How do you access a ParamArray, and pass it to another function,
without copying it.
The Answer: Pointer magic. ParamArrays are really just a
Variant Array - managed by the runtime. For whatever reason though - the
runtime / ide doesn't allow you to get at it's address easily, or even pass it
to another function without making a copy
This particular technique I believe was first pioneered by Matt Curland.
Originally Curland used assembly to get the stack pointer,
add a hard coded offset (depending on the function parameters passed before
the ParamArray) to calculate where the SAFEARRAY** is on the stack, then
return the dereferenced pointer. Then you can safely swap the SAFEARRAY
reference with another SAFEARRAY.
edit: After a a good amount of fumbling, I using Curland's proven methods, with my own self modfying code.
I usually avoid assembly, and dislike mixing it with VB - but here's the cleaned up routines.
just include MParamArray.bas in a project, and you can use the GetParams function.
GetParams takes a single Parameter Offset, and returns a Variant Array, that you can use to pass to other functions.
GetParams steals the Array reference off the stack, without copying the original Array.
without copying it.
The Answer: Pointer magic. ParamArrays are really just a
Variant Array - managed by the runtime. For whatever reason though - the
runtime / ide doesn't allow you to get at it's address easily, or even pass it
to another function without making a copy
This particular technique I believe was first pioneered by Matt Curland.
Originally Curland used assembly to get the stack pointer,
add a hard coded offset (depending on the function parameters passed before
the ParamArray) to calculate where the SAFEARRAY** is on the stack, then
return the dereferenced pointer. Then you can safely swap the SAFEARRAY
reference with another SAFEARRAY.
edit: After a a good amount of fumbling, I using Curland's proven methods, with my own self modfying code.
I usually avoid assembly, and dislike mixing it with VB - but here's the cleaned up routines.
just include MParamArray.bas in a project, and you can use the GetParams function.
GetParams takes a single Parameter Offset, and returns a Variant Array, that you can use to pass to other functions.
GetParams steals the Array reference off the stack, without copying the original Array.
Code:
' SomeForm.frm or Class1.cls
Private Sub Func1(ParamArray Params())
' NOTE: offset calculation from Frame Pointer in a Class Module (.cls) or Form (.frm)
' saved ebp (4) + return address (4) + this ptr (4) + No Params before ParamArray (0)
OtherFunc GetParams(12)
End Sub
Code:
' StandardModule.bas
Private Sub Func2(ParamArray Params())
' NOTE: offset calculation from Frame Pointer (ebp) in a Standard Module (.bas)
' saved ebp (4) + return address (4) + no other params on stack before ParamArray (0)
Dim ParamOffset As Long: ParamOffset = 4 + 4 + 0
If InIDE Then ParamOffset = ParamOffset + 4 ' Standard Module Functions need an extra 4 bytes when debugging
'If you need to pass the array as a ParamArray, to allow modification of ByRef paramaters, Use CallPtr
CallPtr AddressOf Module1.OtherFunc, vbEmpty, RefAry(GetParams(ParamOffset))
End Sub