Yes, inside a function the compiler doesn't know the dimensions of the array and cannot resolve the macro at compile time. Thus you must use run time branching instead of compile time branching as demonstrated by the following macro:
Code: Select all
#Macro GenArrayDescUnknownDim(DESC, ARRAY)
(DESC).dimensions = UBound(ARRAY, 0)
Select Case (DESC).dimensions
Case 1
(DESC)._ptr = @(ARRAY(LBound(ARRAY)))
(DESC).element_len = SizeOf(ARRAY(LBound(ARRAY)))
Case 2
(DESC)._ptr = @(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2)))
(DESC).element_len = SizeOf(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2)))
Case 3
(DESC)._ptr = @(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3)))
(DESC).element_len = SizeOf(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3)))
Case 4
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 5
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 6
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 7
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6), LBound(ARRAY, 7)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 8
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6), LBound(ARRAY, 7), LBound(ARRAY, 8)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
End Select
Scope
Var TotalElements = 1, Diff = 0
For I As Integer = 0 To (DESC).dimensions - 1
(DESC).dimTB(I)._lbound = LBound(ARRAY, I + 1)
(DESC).dimTB(I)._ubound = UBound(ARRAY, I + 1)
(DESC).dimTB(I).elements = (DESC).dimTB(I)._ubound - (DESC).dimTB(I)._lbound + 1
TotalElements *= (DESC).dimTB(I).elements
Diff = Diff * (DESC).dimTB(I).elements + (DESC).dimTB(I)._lbound
Next I
(DESC)._data = CPtr(UByte Ptr, (DESC)._ptr) - Diff * (DESC).element_len
(DESC).size = TotalElements * (DESC).element_len
End Scope
#EndMacro
If the compiler knows the dimensions of the array you have no choice but to use compile time branching. If the compiler does not know the dimensions of the array you have no choice but to use run time branching. You will need both macros to be able to handle any situation:
Code: Select all
Type FBARRAY_DIM
elements As UInteger
_lbound As Integer
_ubound As Integer
End Type
Type FBARRAY_DESC
_data As Any Ptr
_ptr As Any Ptr
size As UInteger
element_len As UInteger
dimensions As UInteger
dimTB(7) As FBARRAY_DIM
End Type
#Macro GenArrayDesc(DESC, ARRAY)
#If UBound(ARRAY, 0) = 1
#Define FIRST_ELEMENT LBound(ARRAY)
#ElseIf UBound(ARRAY, 0) = 2
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2)
#ElseIf UBound(ARRAY, 0) = 3
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3)
#ElseIf UBound(ARRAY, 0) = 4
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4)
#ElseIf UBound(ARRAY, 0) = 5
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5)
#ElseIf UBound(ARRAY, 0) = 6
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6)
#ElseIf UBound(ARRAY, 0) = 7
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6), LBound(ARRAY, 7)
#ElseIf UBound(ARRAY, 0) = 8
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6), LBound(ARRAY, 7), LBound(ARRAY, 8)
#EndIf
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
(DESC).dimensions = UBound(ARRAY, 0)
Scope
Var TotalElements = 1, Diff = 0
For I As Integer = 0 To (DESC).dimensions - 1
(DESC).dimTB(I)._lbound = LBound(ARRAY, I + 1)
(DESC).dimTB(I)._ubound = UBound(ARRAY, I + 1)
(DESC).dimTB(I).elements = (DESC).dimTB(I)._ubound - (DESC).dimTB(I)._lbound + 1
TotalElements *= (DESC).dimTB(I).elements
Diff = Diff * (DESC).dimTB(I).elements + (DESC).dimTB(I)._lbound
Next I
(DESC)._data = CPtr(UByte Ptr, (DESC)._ptr) - Diff * (DESC).element_len
(DESC).size = TotalElements * (DESC).element_len
End Scope
#UnDef FIRST_ELEMENT
#EndMacro
#Macro GenArrayDescUnknownDim(DESC, ARRAY)
(DESC).dimensions = UBound(ARRAY, 0)
Select Case (DESC).dimensions
Case 1
(DESC)._ptr = @(ARRAY(LBound(ARRAY)))
(DESC).element_len = SizeOf(ARRAY(LBound(ARRAY)))
Case 2
(DESC)._ptr = @(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2)))
(DESC).element_len = SizeOf(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2)))
Case 3
(DESC)._ptr = @(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3)))
(DESC).element_len = SizeOf(ARRAY(LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3)))
Case 4
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 5
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 6
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 7
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6), LBound(ARRAY, 7)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
Case 8
#Define FIRST_ELEMENT LBound(ARRAY, 1), LBound(ARRAY, 2), LBound(ARRAY, 3), LBound(ARRAY, 4), LBound(ARRAY, 5), LBound(ARRAY, 6), LBound(ARRAY, 7), LBound(ARRAY, 8)
(DESC)._ptr = @(ARRAY(FIRST_ELEMENT))
(DESC).element_len = SizeOf(ARRAY(FIRST_ELEMENT))
#UnDef FIRST_ELEMENT
End Select
Scope
Var TotalElements = 1, Diff = 0
For I As Integer = 0 To (DESC).dimensions - 1
(DESC).dimTB(I)._lbound = LBound(ARRAY, I + 1)
(DESC).dimTB(I)._ubound = UBound(ARRAY, I + 1)
(DESC).dimTB(I).elements = (DESC).dimTB(I)._ubound - (DESC).dimTB(I)._lbound + 1
TotalElements *= (DESC).dimTB(I).elements
Diff = Diff * (DESC).dimTB(I).elements + (DESC).dimTB(I)._lbound
Next I
(DESC)._data = CPtr(UByte Ptr, (DESC)._ptr) - Diff * (DESC).element_len
(DESC).size = TotalElements * (DESC).element_len
End Scope
#EndMacro
Type MyUDT
Key As Double
Value As String
End Type
Dim MyArray(-5 To 5, 7) As MyUDT
Dim ArDesc As FBARRAY_DESC
GenArrayDesc(ArDesc, MyArray)
Print "data", ArDesc._data
Print "ptr", ArDesc._ptr
Print "size", ArDesc.size
Print "element_len", ArDesc.element_len
Print "dimensions", ArDesc.dimensions
For I As Integer = 0 To ArDesc.dimensions - 1
Print "dimTB(" & I & ")", ArDesc.dimTB(I).elements, ArDesc.dimTB(I)._lbound, ArDesc.dimTB(I)._ubound
Next I
Sleep
'===========================
Sub dothis(M() as MyUDT)
Dim ArDesc As FBARRAY_DESC
GenArrayDescUnknownDim(ArDesc, M)
Print "data", ArDesc._data
Print "ptr", ArDesc._ptr
Print "size", ArDesc.size
Print "element_len", ArDesc.element_len
Print "dimensions", ArDesc.dimensions
For I As Integer = 0 To ArDesc.dimensions - 1
Print "dimTB(" & I & ")", ArDesc.dimTB(I).elements, ArDesc.dimTB(I)._lbound, ArDesc.dimTB(I)._ubound
Next I
end sub
'============================
dothis(MyArray())
Sleep