UDTs containing Dynamic Arrays

New to FreeBASIC? Post your questions here.
Post Reply
gothon
Posts: 225
Joined: Apr 11, 2011 22:22

UDTs containing Dynamic Arrays

Post by gothon »

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.
Last edited by gothon on Apr 14, 2011 20:41, edited 1 time in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Post by rolliebollocks »

You can mimic the functionality of dynamic arrays using pointers...

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
Or you can oversize the array and keep a counter in the UDT, but unfortunately they cannot be resized dynamically.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Post by TJF »

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).
gothon
Posts: 225
Joined: Apr 11, 2011 22:22

Post by gothon »

rolliebollocks wrote:You can mimic the functionality of dynamic arrays using pointers...
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.
TJF 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).
Your method of using macros to store the data in a variable length string is cleaver, I may have to try that. Thanks
gothon
Posts: 225
Joined: Apr 11, 2011 22:22

Post by gothon »

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[].

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
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

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
Post Reply