What are libraries
#1
Form https://staging.qb64phoenix.com/showthread.php?tid=59

PhilOfPerth asks, "Being something of a novice myself (what are "libraries"?),..."

Good question.

Libraries are code that can be used in several different apps or programs without having to rewrite same set of Constants, Types, Subs or Functions, no need to Copy/Paste into your programs.

You just put an Include statement,

         syntax: '$Include: 'MyLibrary.extension' 
            Note the comment at the start and the single quotes around the filename, these are for the compiler.

in the proper place(s) of you program to reuse code from a special "BI" file. It use to be one .BI file in older versions of QB when you had to Declare all your Subs and Functions. 

Now in QB64 there are 2 places to insert code from another file in an Include statement:
An Include statement for Constants and Types goes at the beginning of your program and typically uses the old .BI extension but not mandatory. 

The Include statement for all the Subs and Functions should go at the very bottom of your code, like you are just adding more Subs and Function in. This code file contains just Subs and Functions and the file extension is typically .BM again just a convention so people know what kind of file it is compared to a .BAS file.

Here is an example of a library I made for Arrays of Floats Type:

Here is just a normal looking Bas program dealing with Arrays of Floats
Code: (Select All)
'OPTION _EXPLICIT
' Build a set of Floats Array tools for handling Tomaaz challenge
' Build Floats Array Tools.bm from these
Randomize Timer
Dim i As Long, test$, TomaazTest$
TomaazTest$ = "120 135 345 345 1890 12 120 12 135 712 78 120"
'FOR i = 1 TO 500
'    test$ = test$ + LTRIM$(STR$(INT(RND * 100))) + " "
'NEXT
'test$ = RTRIM$(test$)
test$ = TomaazTest$
Print "Test string: "; test$

ReDim temp(0) As _Float
Split2Floats test$, " ", temp()
uniqueFloats temp()
qSortFloats LBound(temp), UBound(temp), temp()
reverseFloats temp()
Print "Output: "; JoinFloats$(temp(), 0, 10, " ")

'''''$include: 'Floats Array Tools.bm'

'a() must be initialized as redim a(lb to ub)
Sub uniqueFloats (a() As _Float) 'make all the items in the a array unique like a proper set
    Dim i As Long, ti As Long, j As Long, u As Integer, lba As Long
    lba = LBound(a)
    ReDim t(lba To lba) As _Float 'rebuild container
    t(lba) = a(lba): ti = lba
    For i = lba + 1 To UBound(a) 'for each element in array
        u = -1
        For j = lba To ti 'check if not already in new build
            If a(i) = t(j) Then u = 0: Exit For 'oh it is unique is false
        Next
        If u Then 'OK add it to rebuild
            ti = ti + 1
            ReDim _Preserve t(lba To ti) As _Float
            t(ti) = a(i)
        End If
    Next
    ReDim a(lba To ti) As _Float 'goodbye old array
    For i = lba To ti 'now copy the unique elements into array
        a(i) = t(i)
    Next
End Sub

Sub qSortFloats (start As Long, finish As Long, a() As _Float)
    Dim Hi As Long, Lo As Long, Middle As _Float
    Hi = finish: Lo = start
    Middle = a((Lo + Hi) / 2) 'find middle of array
    Do
        Do While a(Lo) < Middle: Lo = Lo + 1: Loop
        Do While a(Hi) > Middle: Hi = Hi - 1: Loop
        If Lo <= Hi Then
            Swap a(Lo), a(Hi)
            Lo = Lo + 1: Hi = Hi - 1
        End If
    Loop Until Lo > Hi
    If Hi > start Then qSortFloats start, Hi, a()
    If Lo < finish Then qSortFloats Lo, finish, a()
End Sub

Sub reverseFloats (a() As _Float)
    Dim i As Long, ti As Long
    ReDim t(LBound(a) To UBound(a)) As _Float
    ti = LBound(a)
    For i = UBound(a) To LBound(a) Step -1 'load t from top to bottom of a
        t(ti) = a(i)
        ti = ti + 1
    Next
    For i = LBound(a) To UBound(a) 'reload a from t
        a(i) = t(i)
    Next
End Sub

'notes: REDIM the a(0) as _float to be loaded before calling Split '<<<<<<<<<<<<<<<<<<<<<<< IMPORTANT!!!!
Sub Split2Floats (mystr As String, delim As String, a() As _Float)
    ' I am hoping _floats will cover any number type
    ' bplus modifications of Galleon fix of Bulrush Split reply #13
    ' http://www.qb64.net/forum/index.php?topic=1612.0
    ' this sub further developed and tested here: \test\Strings\Split test.bas
    Dim copy As String, p As Long, curpos As Long, arrpos As Long, lc As Long, dpos As Long
    copy = mystr 'make copy since we are messing with mystr
    'special case if delim is space, probably want to remove all excess space
    If delim = " " Then
        copy = RTrim$(LTrim$(copy))
        p = InStr(copy, "  ")
        While p > 0
            copy = Mid$(copy, 1, p - 1) + Mid$(copy, p + 1)
            p = InStr(copy, "  ")
        Wend
    End If
    curpos = 1
    arrpos = 0
    lc = Len(copy)
    dpos = InStr(curpos, copy, delim)
    Do Until dpos = 0
        a(arrpos) = Val(Mid$(copy, curpos, dpos - curpos))
        arrpos = arrpos + 1
        ReDim _Preserve a(arrpos + 1) As _Float
        curpos = dpos + Len(delim)
        dpos = InStr(curpos, copy, delim)
    Loop
    a(arrpos) = Val(Mid$(copy, curpos))
    ReDim _Preserve a(arrpos) As _Float
End Sub

Function JoinFloats$ (a() As _Float, aStart As Long, aStop As Long, delimiter As String)
    Dim i As Long, iStart, iStop, b As String
    If aStart < LBound(a) Then iStart = LBound(a) Else iStart = aStart
    If aStop > UBound(a) Then iStop = UBound(a) Else iStop = aStop
    For i = iStart To iStop
        If i = iStop Then
            b = b + LTrim$(Str$(a(i)))
        Else
            b = b + LTrim$(Str$(a(i))) + delimiter
        End If
    Next
    JoinFloats$ = b
End Function

Dang I must have run out of room couldn't continue in last post, so

What are libraries Part 2:

Now just copy all the Subs and Functions from this code, paste it into a New File in IDE, I named this file, 
"Floats Array Tools.bm"

Now you can select all those subs and functions in bas code file and delete it! Then just put one ' single quote before the Include:
Like this now:
Code: (Select All)
'OPTION _EXPLICIT
' Build a set of Floats Array tools for handling Tomaaz challenge
' Build Floats Array Tools.bm from these
Randomize Timer
Dim i As Long, test$, TomaazTest$
TomaazTest$ = "120 135 345 345 1890 12 120 12 135 712 78 120"
'FOR i = 1 TO 500
'    test$ = test$ + LTRIM$(STR$(INT(RND * 100))) + " "
'NEXT
'test$ = RTRIM$(test$)
test$ = TomaazTest$
Print "Test string: "; test$

ReDim temp(0) As _Float
Split2Floats test$, " ", temp()
uniqueFloats temp()
qSortFloats LBound(temp), UBound(temp), temp()
reverseFloats temp()
Print "Output: "; JoinFloats$(temp(), 0, 10, " ")

'$include: 'Floats Array Tools.bm'

Keep the .bm file in same folder as the bas code or worry about paths to the .bm when you include it.

Now here is the beauty of libraries, you can use that same .bm file for another program that also works with Arrays of Floats (I am keeping in same folder as .BM file)

Here I am testing a new fancy Function that will work with the Arrays of Floats that employs already developed tools in my Include file Floats Array Tools.bm
Code: (Select All)
'Test Floats Array Tools Library.bas for QB64
Print UniqueSortSlice$("120 135 345 345 1890 12 120 12 135 712 78 120", "descend", 0, 3)
Print UniqueSortSlice$("120 135 345 345 1890 12 120 12 135 712 78 120", "ascend", -10, 5) 'test join tolerance
Print UniqueSortSlice$("120 135 345 345 1890 12 120 12 135 712 78 120", "descend", 3, 16)
Print UniqueSortSlice$("1 1.1 1.11 1.1 1.11 1. 1.0 1.111 .999999999999999999999999999999999999999", "ascend", 0, 2) 'oh that's nice!!!

Function UniqueSortSlice$ (NumberStr$, ascendDescend$, SliceStart As Long, SliceEnd As Long)
    ReDim temp(0) As _Float
    Split2Floats NumberStr$, " ", temp()
    uniqueFloats temp()
    qSortFloats LBound(temp), UBound(temp), temp()
    If ascendDescend$ <> "ascend" Then reverseFloats temp()
    UniqueSortSlice$ = JoinFloats$(temp(), SliceStart, SliceEnd, " Tomaaz ")
End Function

'$include: 'Floats Array Tools.bm'
Keep in same folder and everything should work.
b = b + ...
Reply
#2
(Is a @bplus automatic because you are the originator of the thread?)

Thanks for the example.  Please say something about the "DECLARE" statements, which are related to a (I think) 2nd meaning of "library".

The "libraries" link on the main page  https://qb64phoenix.com/qb64wiki/index.php/Main_Page
gets you to https://qb64phoenix.com/qb64wiki/index.php/Libraries
which covers "DECLARE LIBRARY" and "DECLARE DYNAMIC LIBRARY",
which applies to DLL, C++, API (and SDL?) libraries,
which is different from the "*.bi" and "*.bm" libraries that you covered?

I've seen another reference to the bi-bm libraries, but I can't remember where.
[ EDIT: In the $INCLUDE Wiki, of course ]
Reply
#3
Code: (Select All)
_Title " MessageBox test - look behind the QB64 app on tool bar if not seen on top. Lean on esc to quit... "

' Thank you FellippeHeitor!
$If WIN Then
    Declare Library
        Function MessageBox (ByVal ignore&, message$, title$, Byval type&)
    End Declare
$Else
    DECLARE LIBRARY ""
    FUNCTION MessageBox (BYVAL ignore&, message$, title$, BYVAL type&)
    END DECLARE
$End If

Const xmax = 800, ymax = 600, PI = 3.141592653589793
Screen _NewImage(xmax, ymax, 32)
_ScreenMove 300, 40
Randomize Timer

Do
    Cls
    drawLandscape
    Color &HFFFFFFFF, &HFF000000
    kind = 1 + 4096 ' 0 is just OK, 1 is OK & Cancel  ' 4096 keeps the message box on top
    Print "Warning a Modal Message Box may come up off screen, you program is waiting for that!."
    m$ = "You might have to look for me off screen. Lean on escape button to quit. Now you should quit seeing me with Cancel."
    answer = MessageBox(0, m$, "Test MessageBox", 4097) ' 4097 for OK = 1 Cancel = 2 Modal on top messagebox
    Print answer ' for kind = 4097 OK = 1 and Cancel = 2

    'cant mess with first parameter?
    _Delay 2
    If answer = 2 Then End
    k$ = InKey$ ' curious if key press in messageBox will interfere with inkey$
    If k$ = "q" Then End
    _Limit 1
Loop Until _KeyDown(27)

Sub drawLandscape
    'needs midInk, irnd

    Dim i As Long, startH As Single, rr As Long, gg As Long, bb As Long
    Dim mountain As Long, Xright As Single, y As Single, upDown As Single, range As Single
    Dim lastx As Single, X As Long
    'the sky
    For i = 0 To ymax
        midInk 0, 0, 128, 128, 128, 200, i / ymax
        Line (0, i)-(xmax, i)
    Next
    'the land
    startH = ymax - 200
    rr = 70: gg = 70: bb = 90
    For mountain = 1 To 6
        Xright = 0
        y = startH
        While Xright < xmax
            ' upDown = local up / down over range, change along Y
            ' range = how far up / down, along X
            upDown = (Rnd * .8 - .35) * (mountain * .5)
            range = Xright + irnd&(15, 25) * 2.5 / mountain
            lastx = Xright - 1
            For X = Xright To range
                y = y + upDown
                Color _RGB(rr, gg, bb)
                Line (lastx, y)-(X, ymax), , BF 'just lines weren't filling right
                lastx = X
            Next
            Xright = range
        Wend
        rr = irnd&(rr - 15, rr): gg = irnd&(gg - 15, gg): bb = irnd&(bb - 25, bb)
        If rr < 0 Then rr = 0
        If gg < 0 Then gg = 0
        If bb < 0 Then bb = 0
        startH = startH + irnd&(5, 20)
    Next
End Sub

Sub midInk (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
    Color _RGB32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##)
End Sub

Function irnd& (n1, n2) 'return an integer between 2 numbers
    Dim l%, h%
    If n1 > n2 Then l% = n2: h% = n1 Else l% = n1: h% = n2
    irnd& = Int(Rnd * (h% - l% + 1)) + l%
End Function

Yes so the top part is telling the compiler to add a function called MessageBox from another language or available from the OS.

Honestly those things are above my pay grade. But they can sure come in handy if you need something beyond QB64 limits.


Using @bplus signaled me that you were directing a note in post directly for me to answer use @ to get attention of any member of forum like requesting a reply from them.
b = b + ...
Reply
#4
How do you guard against the duplication of variable names - same variable name in the main v's the in the library or does it matter?
Reply
#5
(04-24-2022, 04:31 PM)Dimster Wrote: How do you guard against the duplication of variable names - same variable name in the main v's the in the library or does it matter?

Variables in Subs and Functions are private AKA local unless SHARED or CONST from the main code which make them Global. It is the beauty of Subs or Functions over GOSUBs you can use the same variable name x, y, r differently in a Sub or Function and won't change the x, y, r in main code unless you pass through arguments and change it in Sub or Function.

They, variable values, could get messed up if you pass them to a sub or function as arguments and that sub or function changes them. Be careful with that, member, Gets, just caught that happening with permanent color change help question.
b = b + ...
Reply
#6
Thanks BPlus. You earned an A-Plus in my book.

My question was just a "tongue-in-cheek" question, but in answering it, you've given me a new approach to another little niggle I had. I have several word-games that I want to clean up and place somewhere, and I have a prepared word-list that I want to include in several of them. This is quite a long list (it has all the words from the Oxford, with a few "choice" words removed) so I was loth to add it to all of them. Now I see the light at the end of the tunnel, and it's not another express train (no inference here to recent activity on the Forum) Wink
Reply
#7
LOL seeing the light...

A word list doesn't take too long to load from a file into an array.

We've done many a word game at QB64: Crosswords by Qwerkey, Scrabble by Steve McNeill, I did Cryptogram to death and proceeded onto Wordle and Boggle? (was it?). I had a decent WordSearch app but working with Richard Frost AKA ChiaPet it was much improved!

I think I like building the games more than playing, at least as much.
b = b + ...
Reply




Users browsing this thread: 1 Guest(s)