Lesson 20: Libraries

A library is a collection of useful tools that allow a programmer to develop code quickly and efficiently. A library provides pre-written snippets of code that a programmer can utilize over and over instead of recreating the wheel for each and every piece of software.

Imagine that you are creating software to perform conversions between various units of measures, weights, and temperatures. In lesson 2 we create a few programs of this type but in order to do so we had to either know the conversion formulas or research their structure beforehand. The research, coding, and subsequent testing for accuracy of each formula can be very time consuming. It would be a great benefit if another programmer has already done this formula coding and offered the code for use. This is where libraries can be very beneficial. Let's assume another programmer did the coding and you found the library they offer. The library's name is "UnitConversions.BM" and all you need to do is add the library's code to your own with a statement like this:

'$INCLUDE:'UnitConversions.BM'

You now have all the unit conversion formulas offered in the library literally at your finger tips!

A QB64 library is nothing more than a .BAS source code file containing a collection of subroutines and functions. The file's extension is simply changed to .BM (or .BI, we'll get to that later) to identify the file as a library. Most programming languages offer methods of adding libraries to code and , in fact, most commercial and open source software written today relies heavily upon numerous libraries attached to the source code by the programmer. Most programming forums also include a dedicated area for the discussion and sharing of libraries with others. You can find the QB64 Phoenix Edition library discussion area here.

Building a Library

The best way to understand how a library functions is to build one. Let's create the library mentioned above called "UnitConversions.BM" using the unit conversion formulas from lesson 2. We'll then build a small program that utilizes the library to highlight how effective a library is in the hands of a programmer.

Start the IDE and type in the following code. When finished save the code as UnitConversions.BM. This code is also included as UnitConversions.BM in your .\tutorial\Lesson20 directory.

We now have a library with functions that convert between Celsius to Fahrenheit and millimeters to inches. Let's add this library to a program that allows the user to choose the desired conversion. Create a new listing in your IDE and type in the following program. When finished save the code as UnitConversionDemo.BAS. This code is also included as UnitConversionDemo.BAS in your .\tutorial\Lesson20 directory.

Looking at the code listing above you'll notice that the functions UC_F2C(), UC_C2F, UC_i2mm, and UC_mm2i have all been highlighted in green by the IDE identifying them as functions. By including the library on line 44 the IDE considers the functions contained within the library simply part of the main body code.

There are two types of library files that can be created and included within your code. The first one, .BM files, only contain QB64 functions and subroutines. Library files ending in .BM must be placed at the end of your code since the IDE expects all functions and subroutines to appear after the main body. The second type of library files end in .BI. Library files ending in .BI contain variable and type declarations. Since variables declared with DIM, constants created with CONST, and type definitions created with TYPE ... END TYPE need to be at the beginning of code, so do .BI library files.

If you were to try and include variable declarations, type definitions, and/or constants within the same library file as the functions and subroutines the IDE would complain and generate an error. The need to create two different library files is not a common practice amongst programming languages. QB64 requires this behavior simply because the IDE does not have the capability of sorting out which statements go where. Perhaps in the future the IDE will be updated to support everything placed into one file, but for now you'll need to remember most libraries will require two separate files, a .BI that gets placed at the top of the code and a .BM file that gets placed at the bottom of the code. We'll create another library down below that uses both types of files so you can see this in action.

NOTE: Library files are not required to end in .BI and .BM. This naming convention seems to be the most common amongst most QB64 programmers. In fact, back in 2011 when I started writing QB64 libraries I named the top file .TOP and the bottom file .LIB. However, since the convention is overwhelmingly .BI and .BM this tutorial will stick with this naming convention to avoid confusion.

Unwritten Rules

Beyond the requirement for .BI and .BM files there are a few other rules that should be followed when writing libraries. Keep in mind these "rules" are merely suggestions that will help you and others when utilizing your libraries.

Collision Detection Library

Let's build a library that utilizes all of the suggested rules above and as a bonus will greatly aid in the development of your games. In lesson 15 you were introduced to four methods of collision detection; rectangular, circular, line intersection, and pixel perfect. Combining all of these detection routines into one library will save much time and effort when writing your games.

The first thing to consider is the .BI file. Which variables and type definitions do we absolutely need and how can they be designed to be used easily between the library's functions and procedures? Type in the following code and save it as CollisionLibrary.BI when finished. This code is also included as CollisionLibrary.BI in your .\tutorial\Lesson20 directory.

Now it's time for the .BM file which contains the subroutines and functions at the heart of the library. Type in the following code and save it as CollisionLibrary.BM. This code is also included as CollisionLibrary.BM in your .\tutorial\Lesson20 directory.

Now a program is needed to make use of the collision library and test its features. Type in the following code and save it as CollisionLibraryDemo.BAS. This code is also included as CollisionLibraryDemo.BAS in your .\tutorial\Lesson20 directory.

NOTE: You'll also need the files greenoval.PNG and redoval.PNG to execute this code. Both of these files are also included in your .\tutorial\Lesson20 directory.

Finally, no library is complete without documentation explaining how to utilize the library. For personal libraries I create my library documentation within the IDE using REM statements. This way I can simply copy the documentation directly into my main code body at the bottom for easy referral. When I'm finished writing my code I simply delete the documentation lines. The following documentation is included as CollisionLibrary.DOC in your .\tutorial\Lesson20 directory.

This library follows the .BI and .BM file requirements and all of the suggested rules when writing a set of library functions and procedures:

A good example of the use of libraries can be found in the Minesweeper game I wrote. It utilizes three libraries that I wrote and brought together to create the game; A button library to create Windows style clickable buttons on screen, a menu library to create Windows style drop down menus, and graphics Line Input library to create interactive Line Input data fields.

Windows API Calls

QB64 also allows libraries within Windows (.DLL files) to be used as subroutines and functions. This functionality is beyond the scope of this tutorial but you need to be aware this exists. This is an advanced topic but opens up a whole new world of possibilities to the QB64 programmer. The following code uses a subroutine within the Windows kernel to report the physically installed amount of RAM within your computer. This code is included as PhysicalRAM.BAS in your .\tutorial\Lesson20 directory.

NOTE: This code was written by Spriggsy and shared on the QB64 forum here.

If you wish to explore using Windows API calls the best place to start investigating and asking questions is the QB64 Phoenix Edition forum.