-
Jun 27th, 2022, 10:11 PM
#1
Thread Starter
Frenzied Member
[RESOLVED] Create an object array with a length of zero (or UBound = -1)
I'd like to know how to create an object array with a length of zero (or UBound = -1). For example:
Code:
Dim arrMyCalss() As MyClass
arrMyCalss = CreateEmptyArray("MyClass")
Debug.Assert UBound(arrMyCalss) = -1
'--- OR ---
Dim arrObject() As Object
arrObject= CreateEmptyArray(vbObject)
Debug.Assert UBound(arrObject) = -1
Thanks.
-
Jun 28th, 2022, 01:52 AM
#2
Re: Create an object array with a length of zero (or UBound = -1)
Checking against UBound = -1 is nonsense, since UBound(array) = -1 is a valid upper Bound for e.g. Dim MyArray(-5 To -1) As SomeType
An Array with Length=0 IS "Dim MyArray() As SomeType", since it's not allocating any memory for the Array (-Members), except assigning a memory-address for the variable itself.
You can use VarPtr-API to check the SAFEARRAY-Structure for number of Dims
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
-
Jun 28th, 2022, 02:08 AM
#3
Re: Create an object array with a length of zero (or UBound = -1)
The test for an empty array is Ubound() < LBound(), and something entirely different from an unallocated dynamic array.
Last edited by dilettante; Jun 28th, 2022 at 02:19 AM.
-
Jun 28th, 2022, 02:17 AM
#4
Re: Create an object array with a length of zero (or UBound = -1)
SomeClass.cls:
Code:
Option Explicit
Public L As Long
Module1.bas:
Code:
Option Explicit
Private Declare Function SomeClassArray Lib "oleaut32" Alias "SafeArrayCreateVector" ( _
Optional ByVal VT As VbVarType = vbObject, _
Optional ByVal LB As Long = 0, _
Optional ByVal cElements As Long = 0) As SomeClass()
Private Sub Main()
Dim Ary() As SomeClass
Ary = SomeClassArray()
MsgBox UBound(Ary) < LBound(Ary)
ReDim Ary(0)
Set Ary(0) = New SomeClass
Ary(0).L = 15
MsgBox Ary(0).L
End Sub
-
Jun 28th, 2022, 02:52 AM
#5
Hyperactive Member
Re: Create an object array with a length of zero (or UBound = -1)
It might seem like a silly question but what problem are you trying to solve? This tells you if an array is empty (not dimensioned) without any exceptions or API calls.
Code:
If Not Not ArrayName then
arrayIsEmpty = false
else
arrayIsNotEmpty = true
end if
-
Jun 28th, 2022, 07:25 AM
#6
Thread Starter
Frenzied Member
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by Zvoni
Checking against UBound = -1 is nonsense, since UBound(array) = -1 is a valid upper Bound for e.g. Dim MyArray(-5 To -1) As SomeType
An Array with Length=0 IS "Dim MyArray() As SomeType", since it's not allocating any memory for the Array (-Members), except assigning a memory-address for the variable itself.
You can use VarPtr-API to check the SAFEARRAY-Structure for number of Dims
Thank you, Zvoni.
Originally Posted by dilettante
The test for an empty array is Ubound() < LBound(), and something entirely different from an unallocated dynamic array.
Yes
Originally Posted by vbwins
It might seem like a silly question but what problem are you trying to solve? This tells you if an array is empty (not dimensioned) without any exceptions or API calls.
Code:
If Not Not ArrayName then
arrayIsEmpty = false
else
arrayIsNotEmpty = true
end if
I don't seem to understand what you mean yet.
-
Jun 28th, 2022, 07:36 AM
#7
Thread Starter
Frenzied Member
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by dilettante
SomeClass.cls:
Code:
Option Explicit
Public L As Long
Module1.bas:
Code:
Option Explicit
Private Declare Function SomeClassArray Lib "oleaut32" Alias "SafeArrayCreateVector" ( _
Optional ByVal VT As VbVarType = vbObject, _
Optional ByVal LB As Long = 0, _
Optional ByVal cElements As Long = 0) As SomeClass()
Private Sub Main()
Dim Ary() As SomeClass
Ary = SomeClassArray()
MsgBox UBound(Ary) < LBound(Ary)
ReDim Ary(0)
Set Ary(0) = New SomeClass
Ary(0).L = 15
MsgBox Ary(0).L
End Sub
Excellent, that's exactly what I wanted. I'd like to further dig its value.
I want to assign "Dim arrObject(3) As Object" to "Dim arrMyClass() As MyClass" so that arrMyClass becomes an array with 4 Nothing elements.
That is, I want to initialize MyClass-Array via Object-Array. I'm wondering if there is a way to achieve this. Thanks.
Code:
Option Explicit
Private Declare Function SomeClassArray Lib "oleaut32" Alias "SafeArrayCreateVector" ( _
Optional ByVal VT As VbVarType = vbObject, _
Optional ByVal LB As Long = 0, _
Optional ByVal cElements As Long = 0) As SomeClass()
Private Declare Function SomeObjectArray Lib "oleaut32" Alias "SafeArrayCreateVector" ( _
Optional ByVal VT As VbVarType = vbObject, _
Optional ByVal LB As Long = 0, _
Optional ByVal cElements As Long = 0) As Object()
Private Sub Main()
Dim arrSomeClass() As SomeClass
Dim arrObject() As Object
arrSomeClass = SomeClassArray()
arrObject = SomeObjectArray(vbObject, 0, 3)
arrSomeClass = arrObject
End Sub
Last edited by SearchingDataOnly; Jun 28th, 2022 at 07:42 AM.
-
Jun 28th, 2022, 07:45 AM
#8
Addicted Member
Re: Create an object array with a length of zero (or UBound = -1)
Last edited by argen; Jun 28th, 2022 at 07:55 AM.
-
Jun 28th, 2022, 07:57 AM
#9
Thread Starter
Frenzied Member
Re: Create an object array with a length of zero (or UBound = -1)
Hi argen, thank you for your reply.
dilettante has solved my problem in post#1. My new question is in post#7.
-
Jun 28th, 2022, 10:07 AM
#10
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by SearchingDataOnly
Code:
Private Sub Main()
Dim arrSomeClass() As SomeClass
Dim arrObject() As Object
arrSomeClass = SomeClassArray()
arrObject = SomeObjectArray(vbObject, 0, 3)
arrSomeClass = arrObject
End Sub
In case this request is only, because you want the initialization to UBound=-1 more generically
(working with any simple type as Object(), SomeClass(), String(), Long(), etc.) -
then the following might be of use:
Code:
Option Explicit
Private Declare Sub Assign Lib "kernel32" Alias "RtlMoveMemory" (Dst As Any, Src As Any, Optional ByVal CB& = 4)
Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" (ByVal Dims As Long, ByVal pSA As Long) As Long
Private Sub Main()
Dim Arr() As String
InitEmptyArray Arr '<- works generically also for Object(), String(), Long() etc.
Debug.Print LBound(Arr), UBound(Arr), UBound(Arr) - LBound(Arr) + 1, TypeName(Arr)
ReDim Preserve Arr(0 To 3): Arr(0) = 123 '<- test, whether cbElements was set properly
Debug.Print LBound(Arr), UBound(Arr), UBound(Arr) - LBound(Arr) + 1, Arr(0)
End Sub
Public Sub InitEmptyArray(Arr, Optional ByVal Dimensions& = 1)
If IsArray(Arr) Then Erase Arr Else Exit Sub
Dim pSA As Long: Assign pSA, ByVal VarPtr(Arr) + 8
If pSA Then SafeArrayAllocDescriptor Dimensions, pSA Else Exit Sub
Dim SA As Long: Assign SA, ByVal pSA: If SA = 0 Then Exit Sub
Select Case VarType(Arr) And Not 8192
Case vbByte: Assign ByVal SA + 4, 1&
Case vbInteger, vbBoolean: Assign ByVal SA + 4, 2&
Case vbVariant, vbDecimal: Assign ByVal SA + 4, 16&
Case vbDouble, vbDate, vbCurrency: Assign ByVal SA + 4, 8&
Case Else: Assign ByVal SA + 4, 4&
End Select
End Sub
HTH
Olaf
Last edited by Schmidt; Jun 28th, 2022 at 02:38 PM.
-
Jun 28th, 2022, 11:18 AM
#11
Re: Create an object array with a length of zero (or UBound = -1)
Tweak the SafeArrayAllocDescriptor API declare and can be used without wrapping the SA pointer into a Variant like this
Code:
Option Explicit
Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" (ByVal Dims As Long, pSA() As Any) As Long
Private Type MyUdt
ID As Long
End Type
Private Sub Form_Load()
Dim arrObject() As Object
Dim arrUdt() As MyUdt
Call SafeArrayAllocDescriptor(1, arrObject)
Debug.Print UBound(arrObject)
'--- works with UDTs too
Call SafeArrayAllocDescriptor(1, arrUdt)
Debug.Print UBound(arrUdt)
End Sub
Edit: Ooops, there is a problem with using empty UDT array like the one above that we have already discussed here where there are some more ideas too.
cheers,
</wqw>
Last edited by wqweto; Jun 28th, 2022 at 11:31 AM.
-
Jun 28th, 2022, 12:39 PM
#12
Re: Create an object array with a length of zero (or UBound = -1)
I do this all the time. In fact, I've gotten to where I virtually never return undimensioned arrays from functions that return arrays. I'd much rather have one of these 0 to -1 arrays so I can put it straight into a loop (that wouldn't execute).
Code:
Option Explicit
Private Declare Sub SafeArrayAllocDescriptor Lib "oleaut32" (ByVal cDims As Long, ByRef psaInOut As Long)
Public Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (a() As Any) As Long
Public Sub MakeZeroToNegOneArray(pArray As Long, Optional cDims As Long = 1&)
' Works with all array types (numbers, UDTs, objects (early or late), fixed-length strings), except:
' BSTR (String) arrays. Use s() = Split(vbNullString) instead.
' Probably shouldn't be used with arrays IN varants, but a Varant array should be just fine.
' Non-dynamic arrays. This is obvious, but still important to remember.
'
' WARNING: Before calling this, make SURE the array is ERASED.
' WARNING: You can't use REDIM PRESERVE on these things. Just use REDIM TheArray(Low, High)
' We could also call SafeArrayAllocData which would make these things more versatile (allowing Redim Preserve).
'
' Example: Erase SomeArray
' MakeZeroToNegOneArray ArrPtr(SomeArray)
'
SafeArrayAllocDescriptor cDims, ByVal pArray
'SafeArrayAllocData ByVal pArray ' No reason to NOT do this, but we don't. This would allow ReDim PRESERVE.
End Sub
Please read the comments, as they're important. This thing does have a couple of limits (BSTR strings and arrays within variants).
Also, it assumes we're starting with an "Erased" or never dimensioned array.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Jun 28th, 2022, 12:48 PM
#13
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by wqweto
Edit: Ooops, there is a problem with using empty UDT array ...
Seems to work ok for me. I just took my post #12 code and put it into a BAS module, then put the following into a Form1:
Code:
Option Explicit
Private Type MyUdt
i As Long
s As String
End Type
Private Sub Form_Load()
Dim u() As MyUdt
MakeZeroToNegOneArray ArrPtr(u)
Debug.Print LBound(u), UBound(u)
End Sub
Printed out 0 and -1.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Jun 28th, 2022, 01:06 PM
#14
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by Elroy
Seems to work ok for me. I just took my post #12 code and put it into a BAS module, then put the following into a Form1:
Code:
Option Explicit
Private Type MyUdt
i As Long
s As String
End Type
Private Sub Form_Load()
Dim u() As MyUdt
MakeZeroToNegOneArray ArrPtr(u)
Debug.Print LBound(u), UBound(u)
End Sub
Printed out 0 and -1.
Try to follow this with
ReDim Preserve u(0 To 10) As MyUdt
u(0).i = 42
Second line assignment fails with resized UDT arrays but works ok with arrays of scalar (primitive) types.
cheers,
</wqw>
-
Jun 28th, 2022, 02:38 PM
#15
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by wqweto
Try to follow this with
ReDim Preserve u(0 To 10) As MyUdt
u(0).i = 42
Second line assignment fails with resized UDT arrays but works ok with arrays of scalar (primitive) types.
Your "Redim PreserveAndSetValue-Test" fails also with primitive typed Arrays
(have just corrected my code in #10 appropriately to):
Code:
Option Explicit
Private Declare Sub Assign Lib "kernel32" Alias "RtlMoveMemory" (Dst As Any, Src As Any, Optional ByVal CB& = 4)
Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" (ByVal Dims As Long, ByVal pSA As Long) As Long
Private Sub Main()
Dim Arr() As String
InitEmptyArray Arr '<- works generically also for Object(), String(), Long() etc.
Debug.Print LBound(Arr), UBound(Arr), UBound(Arr) - LBound(Arr) + 1, TypeName(Arr)
ReDim Preserve Arr(0 To 3): Arr(0) = 123 '<- test, whether cbElements was set properly
Debug.Print LBound(Arr), UBound(Arr), UBound(Arr) - LBound(Arr) + 1, Arr(0)
End Sub
Public Sub InitEmptyArray(Arr, Optional ByVal Dimensions& = 1)
If IsArray(Arr) Then Erase Arr Else Exit Sub
Dim pSA As Long: Assign pSA, ByVal VarPtr(Arr) + 8
If pSA Then SafeArrayAllocDescriptor Dimensions, pSA Else Exit Sub
Dim SA As Long: Assign SA, ByVal pSA: If SA = 0 Then Exit Sub
Select Case VarType(Arr) And Not 8192
Case vbByte: Assign ByVal SA + 4, 1&
Case vbInteger, vbBoolean: Assign ByVal SA + 4, 2&
Case vbVariant, vbDecimal: Assign ByVal SA + 4, 16&
Case vbDouble, vbDate, vbCurrency: Assign ByVal SA + 4, 8&
Case Else: Assign ByVal SA + 4, 4&
End Select
End Sub
Olaf
-
Jun 28th, 2022, 04:48 PM
#16
Re: Create an object array with a length of zero (or UBound = -1)
Lots of impressive wizardry in this thread. Nonetheless, I'm going to take a shot in the dark here and assume that this is about your transpiler again SDO. If it is not about that feel free to ignore this post.
Reading your OP, I got the impression you want to replicate the object oriented behavior of arrays seen in modern languages like C# or Python. What you must understand is that you cannot graft VB6's arrays 1:1 onto array types in modern high level languages. VB6 arrays are more closely related to C arrays than they are to C# arrays or Python arrays. Arrays are typically full blown objects in modern languages. They may have special compiler support in some cases like in C# to optimize their performance.
Thankfully, as far as transpiling goes, this is one of the easier things to replicate in VB6. You can start by having your transpiler auto-generate a class like this for every array type used in your scripting language:-
Code:
'=====================
NativeArray_String.cls
'=====================
Private g_arr() As String
Private g_len As Long
Public Property Get Length() As Long
Length = g_len
End Property
Public Property Get Item(ByVal index As Long) As String
Item = g_arr(index)
End Property
Public Property Let Item(ByVal index As Long, ByVal value As String)
g_arr(index) = value
End Property
Public Sub SetSize(ByVal size As Long)
If size = 0 Then
Erase g_arr
Else
ReDim g_arr(0 To size - 1)
End If
g_len = size
End Sub
Public Sub SetData(ParamArray data() As Variant)
Dim i As Long
ReDim g_arr(0 To UBound(data))
For i = 0 To UBound(data)
g_arr(i) = data(i)
Next
g_len = UBound(data) + 1
End Sub
The above is one for a String array. Highlighted in red are points where the type of the array is represented so if it were an array of Longs, they would both be Long instead of String. Your transpiler should generate one of each type of array used in code.
Now using VB.Net as a stand-in for your scripting language, the following could be transpiled to VB6:-
Code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim data As String()
'Test for null
Debug.WriteLine(data Is Nothing)
'Create array of size 10
data = New String(9) {}
Debug.WriteLine(data.Length)
'Create empty array
data = {}
Debug.WriteLine(data.Length)
'Assign an array with data
data = {"Hello", "World"}
For i = 0 To data.Length - 1
Debug.WriteLine(data(i))
Next
'Change an element
data(1) = "WORLD!!!!"
Debug.WriteLine(data(1))
End Sub
As this:-
Code:
Private Sub Form_Load()
Dim i As Long
Dim data As NativeArray_String
'Test for null
Debug.Print data Is Nothing
'Create array of size 10
Set data = New NativeArray_String
data.SetSize 10
Debug.Print data.Length
'Create empty array
data.SetSize 0
Debug.Print data.Length
'Assign an array with data
data.SetData "Hello", "world"
For i = 0 To data.Length - 1
Debug.Print data.Item(i)
Next
'Change an element
data.Item(1) = "WORLD!!!"
Debug.Print data.Item(1)
End Sub
This way you get full object oriented behavior from arrays successfully represented in VB6 including the ability to pass the reference by value, straightforward nullability and zero length arrays.
Last edited by Niya; Jun 28th, 2022 at 04:51 PM.
-
Jun 28th, 2022, 05:05 PM
#17
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by wqweto
Try to follow this with
ReDim Preserve u(0 To 10) As MyUdt
u(0).i = 42
Second line assignment fails with resized UDT arrays but works ok with arrays of scalar (primitive) types.
cheers,
</wqw>
Yep, you're correct. But, why are we trying to preserve a 0 to -1 array. I agree that it's a "got'cha", but, if we're careful it'll work just fine.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Jun 29th, 2022, 03:12 AM
#18
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by Elroy
But, why are we trying to preserve a 0 to -1 array.
Usually it's when you append to an dynamic array you just check size and resize if needed and then assign last element If lSize > UBound(arr) Then ReDim Preserve arr(0 To lSize * 2) End If : arr(lSize) = NewEntry or similar.
cheers,
</wqw>
-
Jun 29th, 2022, 08:55 AM
#19
Thread Starter
Frenzied Member
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by Schmidt
In case this request is only, because you want the initialization to UBound=-1 more generically
(working with any simple type as Object(), SomeClass(), String(), Long(), etc.) -
then the following might be of use:
Code:
Option Explicit
Private Declare Sub Assign Lib "kernel32" Alias "RtlMoveMemory" (Dst As Any, Src As Any, Optional ByVal CB& = 4)
Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" (ByVal Dims As Long, ByVal pSA As Long) As Long
Private Sub Main()
Dim Arr() As String
InitEmptyArray Arr '<- works generically also for Object(), String(), Long() etc.
Debug.Print LBound(Arr), UBound(Arr), UBound(Arr) - LBound(Arr) + 1, TypeName(Arr)
ReDim Preserve Arr(0 To 3): Arr(0) = 123 '<- test, whether cbElements was set properly
Debug.Print LBound(Arr), UBound(Arr), UBound(Arr) - LBound(Arr) + 1, Arr(0)
End Sub
Public Sub InitEmptyArray(Arr, Optional ByVal Dimensions& = 1)
If IsArray(Arr) Then Erase Arr Else Exit Sub
Dim pSA As Long: Assign pSA, ByVal VarPtr(Arr) + 8
If pSA Then SafeArrayAllocDescriptor Dimensions, pSA Else Exit Sub
Dim SA As Long: Assign SA, ByVal pSA: If SA = 0 Then Exit Sub
Select Case VarType(Arr) And Not 8192
Case vbByte: Assign ByVal SA + 4, 1&
Case vbInteger, vbBoolean: Assign ByVal SA + 4, 2&
Case vbVariant, vbDecimal: Assign ByVal SA + 4, 16&
Case vbDouble, vbDate, vbCurrency: Assign ByVal SA + 4, 8&
Case Else: Assign ByVal SA + 4, 4&
End Select
End Sub
HTH
Olaf
Very useful, thank you Olaf.
-
Jun 29th, 2022, 08:58 AM
#20
Thread Starter
Frenzied Member
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by wqweto
Tweak the SafeArrayAllocDescriptor API declare and can be used without wrapping the SA pointer into a Variant like this
Code:
Option Explicit
Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" (ByVal Dims As Long, pSA() As Any) As Long
Private Type MyUdt
ID As Long
End Type
Private Sub Form_Load()
Dim arrObject() As Object
Dim arrUdt() As MyUdt
Call SafeArrayAllocDescriptor(1, arrObject)
Debug.Print UBound(arrObject)
'--- works with UDTs too
Call SafeArrayAllocDescriptor(1, arrUdt)
Debug.Print UBound(arrUdt)
End Sub
Edit: Ooops, there is a problem with using empty UDT array like the one above that we have already discussed here where there are some more ideas too.
cheers,
</wqw>
Very useful code and info, thank you, wqweto.
-
Jun 29th, 2022, 08:59 AM
#21
Thread Starter
Frenzied Member
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by Elroy
I do this all the time. In fact, I've gotten to where I virtually never return undimensioned arrays from functions that return arrays. I'd much rather have one of these 0 to -1 arrays so I can put it straight into a loop (that wouldn't execute).
Code:
Option Explicit
Private Declare Sub SafeArrayAllocDescriptor Lib "oleaut32" (ByVal cDims As Long, ByRef psaInOut As Long)
Public Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (a() As Any) As Long
Public Sub MakeZeroToNegOneArray(pArray As Long, Optional cDims As Long = 1&)
' Works with all array types (numbers, UDTs, objects (early or late), fixed-length strings), except:
' BSTR (String) arrays. Use s() = Split(vbNullString) instead.
' Probably shouldn't be used with arrays IN varants, but a Varant array should be just fine.
' Non-dynamic arrays. This is obvious, but still important to remember.
'
' WARNING: Before calling this, make SURE the array is ERASED.
' WARNING: You can't use REDIM PRESERVE on these things. Just use REDIM TheArray(Low, High)
' We could also call SafeArrayAllocData which would make these things more versatile (allowing Redim Preserve).
'
' Example: Erase SomeArray
' MakeZeroToNegOneArray ArrPtr(SomeArray)
'
SafeArrayAllocDescriptor cDims, ByVal pArray
'SafeArrayAllocData ByVal pArray ' No reason to NOT do this, but we don't. This would allow ReDim PRESERVE.
End Sub
Please read the comments, as they're important. This thing does have a couple of limits (BSTR strings and arrays within variants).
Also, it assumes we're starting with an "Erased" or never dimensioned array.
Very useful code, thank you, Elroy.
-
Jun 29th, 2022, 09:01 AM
#22
Thread Starter
Frenzied Member
Re: Create an object array with a length of zero (or UBound = -1)
Originally Posted by Niya
Lots of impressive wizardry in this thread. Nonetheless, I'm going to take a shot in the dark here and assume that this is about your transpiler again SDO. If it is not about that feel free to ignore this post.
Reading your OP, I got the impression you want to replicate the object oriented behavior of arrays seen in modern languages like C# or Python. What you must understand is that you cannot graft VB6's arrays 1:1 onto array types in modern high level languages. VB6 arrays are more closely related to C arrays than they are to C# arrays or Python arrays. Arrays are typically full blown objects in modern languages. They may have special compiler support in some cases like in C# to optimize their performance.
Thankfully, as far as transpiling goes, this is one of the easier things to replicate in VB6. You can start by having your transpiler auto-generate a class like this for every array type used in your scripting language:-
Code:
'=====================
NativeArray_String.cls
'=====================
Private g_arr() As String
Private g_len As Long
Public Property Get Length() As Long
Length = g_len
End Property
Public Property Get Item(ByVal index As Long) As String
Item = g_arr(index)
End Property
Public Property Let Item(ByVal index As Long, ByVal value As String)
g_arr(index) = value
End Property
Public Sub SetSize(ByVal size As Long)
If size = 0 Then
Erase g_arr
Else
ReDim g_arr(0 To size - 1)
End If
g_len = size
End Sub
Public Sub SetData(ParamArray data() As Variant)
Dim i As Long
ReDim g_arr(0 To UBound(data))
For i = 0 To UBound(data)
g_arr(i) = data(i)
Next
g_len = UBound(data) + 1
End Sub
The above is one for a String array. Highlighted in red are points where the type of the array is represented so if it were an array of Longs, they would both be Long instead of String. Your transpiler should generate one of each type of array used in code.
Now using VB.Net as a stand-in for your scripting language, the following could be transpiled to VB6:-
Code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim data As String()
'Test for null
Debug.WriteLine(data Is Nothing)
'Create array of size 10
data = New String(9) {}
Debug.WriteLine(data.Length)
'Create empty array
data = {}
Debug.WriteLine(data.Length)
'Assign an array with data
data = {"Hello", "World"}
For i = 0 To data.Length - 1
Debug.WriteLine(data(i))
Next
'Change an element
data(1) = "WORLD!!!!"
Debug.WriteLine(data(1))
End Sub
As this:-
Code:
Private Sub Form_Load()
Dim i As Long
Dim data As NativeArray_String
'Test for null
Debug.Print data Is Nothing
'Create array of size 10
Set data = New NativeArray_String
data.SetSize 10
Debug.Print data.Length
'Create empty array
data.SetSize 0
Debug.Print data.Length
'Assign an array with data
data.SetData "Hello", "world"
For i = 0 To data.Length - 1
Debug.Print data.Item(i)
Next
'Change an element
data.Item(1) = "WORLD!!!"
Debug.Print data.Item(1)
End Sub
This way you get full object oriented behavior from arrays successfully represented in VB6 including the ability to pass the reference by value, straightforward nullability and zero length arrays.
You've always inspired me a lot when it comes to transpilers. Thank you, Niya.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|