I'm trying to get the dimension of an array via PeekArray
and SafeArrayGetDim
API,
But the "Type mismatch" when compiling.
And if Debug.Print SafeArrayGetDim(PeekArray(TestArray).Ptr)
will work fine.
Please find below the VB code. Any help will be greatful.
Option Explicit
Private Type PeekArrayType
Ptr As Long
Reserved As Currency
End Type
Private Declare Function PeekArray Lib "kernel32" Alias "RtlMoveMemory" ( _
Arr() As Any, Optional ByVal Length As Long = 4) As PeekArrayType
Private Declare Function SafeArrayGetDim Lib "oleaut32.dll" (ByVal Ptr As Long) As Long
Sub GetArrayDimension()
Dim TestArray() As Long
ReDim TestArray(3, 2)
Debug.Print fnSafeArrayGetDim(TestArray)
End Sub
Function fnSafeArrayGetDim(varRunArray As Variant) As Long
Dim varTmpArray() As Variant
varTmpArray = varRunArray
fnSafeArrayGetDim = SafeArrayGetDim(PeekArray(varTmpArray).Ptr)
End Function
Here is a working fnSafeArrayGetDim
function
Option Explicit
#Const HasPtrSafe = (VBA7 <> 0) Or (TWINBASIC <> 0)
#If Win64 Then
Private Const PTR_SIZE As Long = 8
#Else
Private Const PTR_SIZE As Long = 4
#End If
#If HasPtrSafe Then
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
Private Enum LongPtr
[_]
End Enum
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#End If
Public Function fnSafeArrayGetDim(varRunArray As Variant) As Long
Const VT_BYREF As Long = &H4000
Dim lVarType As Long
Dim lPtr As LongPtr
Call CopyMemory(lVarType, varRunArray, 2)
If (lVarType And vbArray) <> 0 Then
Call CopyMemory(lPtr, ByVal VarPtr(varRunArray) + 8, PTR_SIZE)
If (lVarType And VT_BYREF) <> 0 Then
Call CopyMemory(lPtr, ByVal lPtr, PTR_SIZE)
End If
If lPtr <> 0 Then
Call CopyMemory(fnSafeArrayGetDim, ByVal lPtr, 2)
End If
End If
End Function
Private Sub Form_Load()
Dim TestArray() As Long
ReDim TestArray(3, 2)
Debug.Print fnSafeArrayGetDim(TestArray)
End Sub
You don't need PeekArray
as you are dealing with pure Variant
s not arrays like Variant()
(array of Variant
s), Long()
(array of Long
s) or Byte()
(array of Byte
s) generally a type ending with ()
in VB6 is so called SAFEARRAY
in COM parlance.
So your varRunArray
is a pure Variant
that points to a SAFEARRAY
in its pparray
member which is located at VarPtr(varRunArray) + 8
. Once you get this pointer you must heed the VT_BYREF
flag in Variant
's vt
which introduces a double indirection (you have to dereference lPtr = *lPtr
once more). At this point if you get a non-NULL pointer to the SAFEARRAY
structure then the cDim
member is in the first 2 bytes.