Hi, I'm new to FB but I am familiar with other versions of BASIC and C. What I'm trying to do is convert a VB6 source file that I made to FB. Apparently FB supports dynamic arrays using the same syntax as VB6, and also supports user defined types using similar syntax.
However, the FB compiler does not seem to understand UDTs containing dynamic arrays. My program contains a lot of use dynamic arrays of structures themselves containing dynamic arrays. If anyone knows of a good way to achieve the same functionality with minimum changes to the code syntax, I would very much appreciate it.
If anyone is curious, the file I'm converting you can actually go to:
http://www.vast3d.com/shapeedit/Programming.html
and look at it.
UDTs containing Dynamic Arrays
UDTs containing Dynamic Arrays
Last edited by gothon on Apr 14, 2011 20:41, edited 1 time in total.
-
- Posts: 2655
- Joined: Aug 28, 2008 10:54
- Location: new york
You can mimic the functionality of dynamic arrays using pointers...
Or you can oversize the array and keep a counter in the UDT, but unfortunately they cannot be resized dynamically.
Code: Select all
type sometype
as integer nVals
as integer ptr somevar
declare sub AddVal ( byval newval as integer )
end type
sub sometype.AddVal ( byval newval as integer )
nVals += 1
somevar = reallocate ( somevar, nVals*(sizeof(sometype)) )
somevar[nVals-1] = newval
end sub
dim as sometype s
for i as integer = 1 to 10
s.AddVal(i)
next
for i as integer = 0 to s.nVals-1
print s.somevar[i]
next
sleep
I made a macro for dynamic arrays in UDTs here.
It uses Sval(Index, Value) to set a value and Gval(Index) to get a value (some rewriting of your code will be needed, only one dimensional arrays yet).
It uses Sval(Index, Value) to set a value and Gval(Index) to get a value (some rewriting of your code will be needed, only one dimensional arrays yet).
Yes obviously, however correctly using ALLOC functions is a messy business. I think it would be best if I could just make a pointer to a dynamic array, then all I would need to do is create it and destroy it in the constructor/destructor. I'm guessing that FB isn't able to create a new dynamic array on the heap and return a pointer to it though.rolliebollocks wrote:You can mimic the functionality of dynamic arrays using pointers...
Your method of using macros to store the data in a variable length string is cleaver, I may have to try that. ThanksTJF wrote:I made a macro for dynamic arrays in UDTs here.
It uses Sval(Index, Value) to set a value and Gval(Index) to get a value (some rewriting of your code will be needed, only one dimensional arrays yet).
Ok, I ultimately decided to combine all our ideas together by effectively reimplementing dynamic arrays using a series of Macros that allocate memory using New[].
All you have to do to use these macros is add a destructor to free any arrays in your structure when it leaves scope, use brackets instead of parentheses to access elements and substitute the appropriate macro for ReDim, UBound, etc. You can even use them with dynamic arrays not inside UDTs.
This is illustrated in the following example, which creates an array of polygons, (each of which is itself an array of points), then draws them.
Code: Select all
#Ifndef NULL
#Define NULL 0
#EndIf
#Define VA_UBOUND(ARRAY) ARRAY##_UBound
#MACRO VARARRAY(ARRAY, VARTYPE)
ARRAY As VARTYPE Ptr = NULL
ARRAY##_UBound As Integer = -1
#EndMacro
#Macro VA_FREE(ARRAY)
If ARRAY <> NULL Then Delete[] ARRAY
ARRAY = NULL
#EndMacro
#MACRO VA_REDIM(ARRAY, NEW_UBOUND, VARTYPE)
If ARRAY <> NULL Then Delete[] ARRAY
ARRAY##_UBound = NEW_UBOUND
ARRAY = New VARTYPE[ARRAY##_UBound + 1]
#EndMacro
'ReDim Preserve shortened to ReDimP
#MACRO VA_REDIMP(ARRAY, NEW_UBOUND, VARTYPE)
If ARRAY = NULL Then
ARRAY = New VARTYPE[NEW_UBOUND + 1]
Else
Scope
Dim Temp_Array_Ptr As VARTYPE Ptr = New VARTYPE[NEW_UBOUND + 1]
Dim Temp_Array_Index As Integer
If NEW_UBOUND > ARRAY##_UBound Then
For Temp_Array_Index = 0 To ARRAY##_UBound
Temp_Array_Ptr[Temp_Array_Index] = ARRAY[Temp_Array_Index]
Next Temp_Array_Index
Else
For Temp_Array_Index = 0 To NEW_UBOUND
Temp_Array_Ptr[Temp_Array_Index] = ARRAY[Temp_Array_Index]
Next Temp_Array_Index
End If
Delete[] ARRAY
ARRAY = Temp_Array_Ptr
End Scope
End If
ARRAY##_UBound = NEW_UBOUND
#EndMacro
This is illustrated in the following example, which creates an array of polygons, (each of which is itself an array of points), then draws them.
Code: Select all
const PI = 3.14159265358979323846#
Type Vector2d
X As Single
Y As Single
End Type
Type Polygon
VARARRAY(Points, Vector2d)
Color As Integer
Declare Destructor()
End Type
Destructor Polygon()
VA_FREE(Points)
End Destructor
Dim Polys() As Polygon
Dim I As Integer, J As Integer, Angle As Single
'Create Structures containing some polygons
ReDim Polys(5) As Polygon
For I = 0 To UBound(Polys)
VA_ReDim(Polys(I).Points, I + 2, Vector2d)
For J = 0 To VA_UBound(Polys(I).Points)
Angle = 2*Pi * J / (VA_UBound(Polys(I).Points) + 1)
Polys(I).Points[J].X = 20 * (3*I + 2 + Cos(Angle))
Polys(I).Points[J].Y = 20 * (2 + Sin(Angle))
Next J
Polys(I).Color = I + 1
Next I
'Draw the polygons
Screen 15
For I = 0 To UBound(Polys)
J = VA_UBound(Polys(I).Points)
Line (Polys(I).Points[J].X, Polys(I).Points[J].Y) _
-(Polys(I).Points[0].X, Polys(I).Points[0].Y), Polys(I).Color
For J = 1 To VA_UBound(Polys(I).Points)
Line -(Polys(I).Points[J].X, Polys(I).Points[J].Y), Polys(I).Color
Next J
Next I
Sleep