PureBasic Survival Guide I - General
PureBasic Survival Guide
a tutorial for using purebasic for windows 5.70 LTS

Part 0 - TOC
Part I - General
Part II - Converts
Part III - Primer I
Part IV - Primer II
Part V - Advanced
Part VI - 2D Graphics I
Part VII - 2D Graphics II
Part X - Assembly
Part XI - Debugger
Part XII - VirtualBox
Part XIII - Databases
Part XIV - Networking
Part XV - Regular Expressions
Part XVI - Application Data
Part XVII - DPI
Part XXVII - Irregular Expressions
Part XXIX - Projects
 

Part I - General.
v8.04 26.01.2019

1.1 First this
1.2 Set Up
1.4 Basic building blocks
1.5 Variables and expressions
1.6 Winapi calls
1.7 Other
1.8 My (stupid) questions
1.9 Some sample code
1.10 Thanks!


1.1 First this
 

Note

  • Note: I'm updating these pages after yet another long period of inactivity.
  • Any stuff between << and >> contains my working notes.
  • If you stumble over a << werkpunt >> then pay extra attention, it's a section that I might be mucking around with...
  • All updated and new stuff is in red. All other colours either still applies, or hasn't been checked yet :-)


Which version of PureBasic does this apply to?

The Survival Guide is (in)frequently updated... whenever I feel like it :-) I will try to mark all major changes to the previous version of the Survival Guide in red. I'm bound to miss something, or make mistakes. These pages have been written over time, with different versions of PureBasic and Windows.

Some sections may no longer apply, or work differently with newer versions of PureBasic or Windows! Check!

Here's how to check how old code and examples are, and perhaps that might help you to see if if the examples and explanations still apply:

  1. Check the 'timestamp' on the right top of the page, the number shown there is the year I made the most recent (big) change to the page.
  2. Check the line 'using purebasic x.xx for windows' in the upper left corner of this page (just below the words 'PureBasic Survival Guide') to verify for the version this text applies to.
  3. Most (running) code samples start with one or two lines identifying which version of PureBasic I used when I wrote them.


History

On October 5, 2003, the user BluezNL posted the following:

I put most of my stupid mistakes together on a page, a sort of survival guide... :wink:
If anyone knows his stuff and has nothing better to do... did I make any mistakes?
Other than the ones that caused me to set up that page :-)
And it's been 15 years since!
 

Feel the Pure Power!

PureBasic exists in different flavours and versions (Windows, Linux, Mac OS-X, Amiga). In this guide I will limit myself to PureBasic for Windows. (The Windows version is perhaps the most mature, but the Linux and Mac versions are getting better every day.)

These pages help you getting started with the Windows version of PureBasic, which is a programming language. (Duh! I bet you didn't see that one coming!). These pages started as a form of self help, then turned into a sort of tutorial / reference / snippet collection, and now have become... euh... a mess I guess :-) And they have been a mess for the last decade...

Please note that this is not an official guide, and that I am in no way part of the official PureBasic team. All mistakes are mine (except those made by others, of course :-)) Consider this work a tribute to the great work AlphaSound & Co did.
 

How this document is organized

These pages are spread over five seperate sections (with a bit of historic overlap and duplication):

0 - Table of Contents - search this space for specific keywords
I - General - some generic information and a quick introduction to PureBasic language elements
II - Converts - quick guide for converts from older versions, other Basic variants or other languages
III to IV - Primer I and Primer II  - for those less experienced or running into issues
V to XXVII - Different subjects
If you're an experienced user / programmer, read on. If things look confusing or complicated you may want to go to the Primer pages.
 

It's Basic, Jim. But not as we know it

No. I am not going to tell you how to program, or how to learn Basic (well, perhaps a little). I am only going to point out some things that caused me loads of problems due to misunderstandings. Some of it might be obvious to you, but not to me at the time... (Which was my prime motivation to write this guide.)

This thing called PureBasic is different... But that doesn't mean this is a bad programming language, or that basic itself is a bad programming language. It just depends what you are going to do with it. I switched over to PureBasic (or PB or Pure as it is lovingly called) when my previous language of choice GfaBasic disappeared...

PureBasic does have its own flavour though...

Don't listen to anybody who says any programming in Basic is bad, that any program in Basic resembles a plate of spaghetti, and that Basic is oh so slow. What counts is not the language a program is written in, but how well a program does what it is supposed to do. (And I would like to invite the sceptics to have a good look at the aspects of any modern 'Basic' language. They might be in for a surprise.)

One word of warning though: PureBasic is a procedural language, not an object oriented language.

There are some user created pre-processors, and perhaps one day there will be a little OOP (though I would not hold my breath as the developers have said 'no' more than once). Fortunately, it is still very usable.
 

What it is

PureBasic? Well. A programming language. It's a kind of Basic (check WikiPedia) with it's own deviations from the standard syntax.

  • compact, extensive libraries including 2d and 3d graphics
  • for Windows, Linux, Mac and Amiga (in decreasing levels of development and support)
  • compact and fast code
  • bug fixes, active user base, great community
  • developed by a small international team under a French lead programmer
  • no interpreter but a fast compiler, complete with debugger
  • it's a moving, living language


Where to get it

PureBasic costs 79 euro (in August 2008 it was 79 euro, and in April 2016 it was still 79 euro!) and can be bought here. You can use a credit card or euro cheque.  Buying the official full version includes life time updates. So better be fast before the developer changes his mind regarding the license scheme!

There is also a demo version available so you can try before you buy. Go to purebasic.com for more information, download and try. The demo version has a number of limitations, of which the most obvious is the lack of WinApi support (that's any command ending on an underscore).

Don't worry. I don't get any money for this free plug. So let's hit the road and see what this baby can do...


1.2 Set Up


PureBasic Editor and Compiler

To install simply run the downloaded executable. That's it. You should be able to install it over any older version, but I'd rather not take chances. As it's so small, installing is a breeze, and it definitely doesn't hurt to keep a copy or two around.
 

Editor

In the past I suggested the use of JaPBe, but the included editor (since 4.20 or so) does a fine job these days. The PB editor has been adopting many features of JaPBe, honoured some user requests, and now includes some functionality that was provided by third party applications in the past (such as my own CodeCaddy). So, stick to the native PB IDE and you'll be fine.


Additional help files for WinAPI and Assembly
 

PureBasic v4.40

Planning to do some programming using WinApi calls? Then you'll might find some use for these:

  1. look on the internet for the file WIN32.HLP (here's a copy)
  2. download it (now that's obvious)
  3. unpack it if necessary
  4. create a 'Help' folder in your purebasic directory, if there isn't one yet
  5. copy the WIN32 help files to the 'Help' folder in your purebasic directory
If you are inside the editor and press F1 while the cursor is parked 'above' a winapi call, a help window will pop up with more information... Neat! 

(Note: there are three versions of the win32.hlp file... an old one dating back to 1996 with all images removed (approx. 12 MB), a re-edited one (approx. 24 MB) which includes all images and some additional WinApi descriptions, and somewhere (although I've never seen it) must be the original file... It doesn't matter much which one you use though.)

A similar thing can be done for inline assembly:

  1. download the file ASMHELP.ZIP
  2. unpack and place ASM.HLP in the 'Help' folder
  3. enable Inline ASM support under compiler options
  4. move the cursor over the INC statement of the example and press F1
If the links above are no longer working then start up your Google and go search. These files are quite common. And if that didn't work, I've included them here as well...

You can now type some assembly and hit F1 for more info on that instruction. I don't know why, but for some people F1 does launch WIN32.HLP but not ASM.HLP... strange. You can still access those help files from the IDE using Help / External help.

Here's a little example to test it with:

EnableASM
a = 1
a = a+1
#SM_CMONITORS = 80
Debug GetSystemMetrics_(#SM_CMONITORS)    ; this is an example of a WinAPI call
INC a                                     ; this is an example of inline ASM
Debug a
DisableASM


PureBasic 5.61

The use of .HLP files no longer works under Windows 10. I haven't tried it with the most recent version of PureBasic on something else but Windows 10, to be honest.
 

Help files and newer versions of Windows
 

Windows XP, Vista, 7, 8

Keep in mind that the WIN32.HLP file is old... If you need all information on all API's, in particular the newer ones, it's probably better to check on the Internet, and / or download the MicroSoft Platform SDK. You should be able to find most (if not all) of this information online as well, on msdn.microsoft.com. If you still want to use .HLP files on Vista, Windows 7 or 8, you will have to download and install winhlp32.exe from Microsoft. You will be prompted by an error message the first time you try to open a .HLP file, which will then allow you to download the right program.
 

Windows 10

Microsoft discontinued WinHelp a long time ago but allowed the installation of (older versions of) WinHelp up to Windows 8. Unfortunately this is no longer possible under Windows 10.

I found an ASM.CHM file, as well as a WIN32.CHM file, but these are not recognized and opened by PureBasic, unfortunately.


Tutorials and documentation

PureBasic was traditionally a bit lacking in the documentation and tutorials department, but things have improved greatly since 4.00, have a good look at the included help file (F1).

On the PureBasic website you will find a 1200+ page .PDF file called (surprisingly) PureBasic.PDF. I suspect it's the same thing as the onboard help file PureBasic.CHM, but obviously I haven't checked all those 1200 pages :-)

There is some good stuff to be had at purearea.net but be aware, some is in German, and some examples are based on older versions of PureBasic.

Kale was so kind to offer his PureBasic Beginner's Guide for free. It may not be entirely up-to-date with the latest version of PureBasic, but it's a very good source of information. I've added a copy here.

Yet, in my opinion, the ultimate source of wisdom is the PureBasic forum. Feel free to ask stupid questions. I've done that more than enough myself :-) Please note that on the forum there may be a lot of older code floating around, as there were quite a few improvements over time, but its relatively easy to rewrite them.


1.3 The PB IDE
 

I guess it's pretty much inspired by JaPBe (which itself was based upon an earlier version of the standard PB editor itself) and though at one time it was rather limited it has become my editor of choice.


Fold and unfold

To fold or unfold use the plus or minus boxes behind the line number, or use [F4].

In the IDE you can specify what can be folded, this is a great way to be able to fold enumeration or data section blocks! See the menu item File / Preferences / Editor / Folding.


Reformat

Yeah, the IDE can now format your code 'on the fly', as well as upon your request. Highlight a section of your code and hit [Ctrl] + [I].


AutoComplete

When typing code, the IDE will show you 'possibilities', ie. commands, variable names, procedure names, structure members etcetera. What is shown, can be set here: File / Preferences / Editor / AutoComplete.

I prefer to display everything in the AutoComplete list except for ASM keywords and Interfaces. I also prefer to use [Esc] and [Enter] for escaping and selecting the suggested word. These shortcuts can be set under File / Preferences / General / Shortcuts, where you will find at the bottom of the list the options 'Close the AutoComplete Window' and 'Insert the selected AutoComplete Word'.


Multiline

Yes! Finally :-) Segments of code can be spread over multiple lines, like this:

x.s = "b" +    ; comments are allowed
      "b"      ; as you can see here
Debug x
;
a = 1 : b = 2 : c = 3
If a = 1 And
   b = 2 And
   c = 3
  Debug "Ok"
EndIf
If a line of code ends on a plus, minus, pipe, And, Xor, Or, then it will be regarded as a multiline statement.

(CodeCaddy used a different approach, but the two do not bite each other.)
 

Online syntax check

Sorry GfaBasic users. No such thing.

It seems at one time an online syntax check was in the plans, but it got shelved in favour of other goals.


Session History

As of 5.50 (5.40?) PureBasic keeps a copy of old versions of your code in a local database. This is great if you accidentally edited your code, and need to retrace your steps because something broke... (And you know that does happen, don't you?)

You can find this function under File / Session History. The help file did not include any details, but you can configure this function via File / Preferences / Editor / Session History and that helps to explain the mechanism. Of course, Session History is no replacement for backups!


Other shortcuts?

A few, here is an (incomplete) list of PB IDE vs. JaPBe shortcuts... You can change all the PB IDE shortcuts though. Some functions do not exist in the PB IDE, others do not exist in jaPBe.
 

JaPBe PB IDE function
v1.4.4.18 v4.30
help
[F1] [F1] help on the selected keyword, api call or asm instruction (see here)
[Alt] + [A] {Alt] + [A] asci table
[Alt] + [S] [Alt] + [S] structure viewer (browse predefined structures)
move
[Ctrl] + doubleclick [Ctrl] + doubleclick jump to the place in the code where that procedure or constant has been declared
shift + F3 same as ctrl + doubleclick
[F4] [Ctrl] + [L] jump back after using [Ctrl] + doubleclick
[Ctrl] + [G] [Ctrl] + [G] goto line 'n'
format
[Tab] [Tab] insert a tab or indent all selected code
[Shift] + [Tab] the opposite of tab
[Shift] + [Tab] jump one tab position backwars
[Ctrl] + [Tab] [Ctrl] + [I] auto format selected code
[Ctrl] + [B] [Ctrl] + [B] comment out the selected text (insert a ';' in front of each and every selected line)
[Ctrl] + [Shift] + [B] [Alt] + [B] uncomment the selected text (remove the ';' in front of all the selected lines)
[F4] (un)fold a procedure
[Ctrl] + [F4] (un)fold all procedures
select
doubleclick doubleclick select word / line
edit
[Ctrl] + [Z] [Ctrl] + [Z] undo
run
[F5] compile and run with debugger off
[F6] compile and run with debugger on
[F5] compile and run

Notice that you can change (almost?) all keyboard shortcuts yourself, go to File / Preferences / General / Shortcuts.
 

The next section is aimed at more experienced programmers that just want to have a peek at PureBasic's features. Because they consider switching over, or have done so already.

If things are unclear consider reading the Primer first.


1.4 Basic building blocks


Standard fare...

Most of the regular commands are here. If you've been gone for a long time you might notice that PureBasic does not use line numbers... just kidding, you already knew that :-) If you didn't, better start with the Primer first... (This page is about to get somewhat dense.) I am even considering a 'total beginners guide to basic' but that's not there yet, and may never be...

Okay, some characteristics so you know what you can expect...

  • flowcontrol: all regular Basic commands such as If Then Else Endif / While Wend / Repeat Until / Select Case EndSelect etcetera
  • the regular basic conditional expressions like If <exp> = <exp> etc. and variable assignments <var> = <exp>
  • strings, signed bytes, signed words, signed longs, pointers (a variation on signed longs), doubles, quads, and chars
  • most 'common' 'Basic' functions (sometimes a different syntax, for example FindString instead of InStr etc.)
  • special functions and keywords for buttons, windows etc. in PureBasic terminology dubbed 'gadgets'
  • libraries and commands for images, 2d games (sprites etc.), some audio and 3d
  • compact resulting exe, only the used commands and / or libs make it into the final executable (uh, mostly)
  • it's a procedural language (C, Pascal, GfaBasic etc.) ie. programs are build up using multiple <procedurename>( <parameters> ) calls
  • no (or very little) object oriented stuff
  • available in 32 and 64 bit versions
Note: as of version 5.50 PureBasic is Unicode only! The so-called Ascii mode is no longer supported!


Code order and Declare

Pure compiles top to bottom. In other words, if you want to use something you got to define it first. The following will compile:

; survival guide 1_4_100 code order
; pb4.40b1
;
Procedure test1()
  ; do nothing
EndProcedure
;
Procedure test2()
  test1()               ; no problem calling test1() as it was defined before test2() called it
EndProcedure
;
test2()
And this will not compile:
test1()                 ; can't compile as test1() is not yet defined
;
Procedure test1()
  test2()               ; can't compile as test2() is not yet defined
EndProcedure
;
Procedure test2()
  ; do nothing
EndProcedure
... unless you tell the compiler that something is coming up by using Declare().
; survival guide 1_4_101 code order
; pb4.40b1
;
Declare test1()
Declare test2()
;
test1()
;
Procedure test1()
  test2()
EndProcedure
;
Procedure test2()
  ; do nothing
EndProcedure

Procedures and functions

Functions and procedures are treated the same way.

Call a procedure :

Procedure test3()
  ; do nothing
EndProcedure
;
test3()
Call a procedure (function) and retrieve the return value:
Procedure.l test4()       ; tell the compiler what type of variable will be returned
  ProcedureReturn 1
EndProcedure
;
a.l = test3()
Call a procedure with a value:
Procedure.l test5(a.l)    ; what goes out and what goes in...
a = a+1
  ProcedureReturn a
EndProcedure
;
b.l = 1
c.l = test5(b)

Procedure parameters and the stack

PureBasic uses the same approach as C for passing parameters on to a procedure. Parameters are pushed on the stack from right to left. In most cases it doesn't matter, but it is something to be aware of:

Procedure.l test6(x.l)
  debug x.l
EndProcedure
;
Procedure.l test7(a.l,b.l,c.l,d.l,e.l)
Endprocedure
;
test7(test6(1),test6(2),test6(3),test6(4),test6(5))        ; will output 5 4 3 2 1 !
Here's another example, this one illustrates the difference between expression evaluation (left to right) and parameter passing (right to left):
Procedure.l d(x.l)
  Debug x
EndProcedure
;
a.l = d(1)+d(2)+d(3)
;
Procedure.l e(x.l,y.l,z.l)
EndProcedure
;
a.l = e(d(1),d(2),d(3))
It will list 1, 2, 3, then 3, 2, 1.


Input and output

During development, the Debug command comes in handy... It will display text or variables in a dedicated debug window.

Debug "test message"
Debug variable
(Follow this link for more ifnormation on the debugger.)

For console applications (Dos prompt stuff or simple things that don't need a real 'Windows window', you can use the console. To generate a real 'console' application, you have to set under compiler options the executable format to 'console'. The Print() command only works on a console.

OpenConsole()
PrintN("press any key to continue")
Repeat
  Delay(100)
Until Inkey()<>""
Obviously, 'normal' Windows applications have to open a window first to display any output. Obviously there are commands in PureBasic to do so. See all stuff on windows and gadgets.


1.5 Variables and expressions
 

Declarations

You don't have to declare a variable before using it, except for structures and arrays.

Before digging in: if you're a beginner then stick to three variations: .a for bytes from memory, .d for floating point calculation (antything with fractions) and .i for everything else.

When used the first time, you tell the compiler what type a variable is. Most numeric types are 'signed' but as of 4.40b1 some new unsigned types have shown up.

; survival guide 1_5_100 variables and expressions
; pb 5.70 LTS
;
; basic types
;
a.a = 255                   ; an unsigned byte (8 bits, 0 to +255)
b.b = 255                   ; a signed byte (8 bits, -127 to +127)
c.c = 'c'                   ; a single character, 2 bytes in unicode
u.u = 1                     ; an unsigned word (16 bits, 0 to +65535)
w.w = 1                     ; a signed word (16 bits, -32767 to +32767))
l.l = 1                     ; a signed long (32 bits)
i.i = 1                     ; a signed integer (either 32 or 64 bits depending on platform)
q.q = 1                     ; a signed quad (64 bits aka 8 bytes)
;
; floats and pointers
;
f.f = 1.3                   ; a float (4 bytes)
d.d = 1.3                   ; a double float (8 bytes)
*p = @a                     ; a pointer (either 32 or 64 bits) points to a piece of memory
;
; strings
;
s.s = "appeltaart"          ; a string (10 characters in unicode means 20 bytes excluding terminating zeroes)
s$ = "appeltaart"           ; another string (a.s and a$ are considered seperate variables)
fs${40} = "appeltaart"      ; a fixed length string, note the different type of brackets {} not ()!
;
Debug SizeOf(a)             ; 1, returns the amount of bytes reserved in memory for an unsigned byte, ie. 1 byte
Debug SizeOf(b)             ; 1
Debug SizeOf(c)             ; 1
Debug SizeOf(u)             ; 2
Debug SizeOf(w)             ; 2
Debug SizeOf(l)             ; 4
Debug SizeOf(i)             ; 4 or 8, depending on 32 bits or 64 bits mode
Debug SizeOf(q)             ; 8
Debug ""
Debug SizeOf(f)             ; 4
Debug SizeOf(d)             ; 8
Debug SizeOf(*p)            ; 4 or 8 bytes, depending on 32 bits or 64 bits mode
Debug ""
Debug s                     ; outputs the string itself
Debug Len(s)                ; 10, appeltaart is 10 characters long
Debug SizeOf(s)             ; 4 or 8, this returns the length of an internal string pointer, not the length of the string!
Debug StringByteLength(s)   ; 20, the length of the string in memory excluding terminating zeroes
Debug fs$                   ; outputs the string itself
Debug Len(fs$)              ; 10, returns the length of the string in characters
Debug SizeOf(fs$)           ; 80, returns the amount of bytes reserved for the string in memory
Debug StringByteLength(fs$) ; 20, returns the length of the string in bytes
When you reuse a variable, you don't have to specify its type again.
a.l = 1                 ; the first time, so say what it is
a = 3                   ; next time you don't have to specify the type
a.l = 2                 ; although it doesn't matter if you do
The default type is .i or 'integer'. The size of .i depends on the platform / compiler version!
a = 1                   ; no type defined so it's an integer
a.i = 2                 ; no error here as it's the same type as before
You cannot use the same name for different variable types. In most other basics you could say:
a$ = "appel"
a% = 1
Not so in PureBasic:
a.s = "appel"
a.l = 1                 ; can't do this, the variable a is already declared as a string
But the following is allowed...
a$ = "appel"            ; the $ is considered part of the name AND turns 'a$' into a string variable
a.l = 1                 ; a$ and a.l are different variables so this is possible
a$.s = "appel"          ; of course doesn't make sense, the $ already tells us a$ is a string variable
Note that * and $ are the exception. (Think of them as being part of the variable name AS WELL AS type definition if that makes you happier :-))
a.s = "appel"
a$ = "banana"           ; a$ and a.s are effectively different variables!
b.l = 1
*b = 2                  ; b.l and *b are effectively different variables!
Most numeric variables are signed! This can cause some surprises if you don't pay attention.
; survival guide 1_5_101 signed and unsigned
; pb 4.40b1
;
OpenConsole()
;
b.b = 247                   ; .b stands for a signed byte
PrintN(Str(b.b))            ; will print -9
PrintN(StrU(b.b,#PB_Byte))  ; will print 247
;
a.a = 247                   ; .a stands for an unsigned byte
PrintN(Str(a.a))            ; will print 247
PrintN(StrU(a.a,#PB_Byte))  ; will print 247
;
Repeat
Until Inkey() <> ""
(Don't forget, to use PrintN() we need a console to be open!)

PureBasic has a specific way of dealing with type conversion and expression evaluation, which is described in more detail here.


Strings in memory

All regular strings are zero terminated and cannot contain a null character (asci code 0). If they contain a zero, they will be truncated! If you are in a habit of using strings as buffers for binary content (that could contain one or more zero's) you will have to use so called 'fixed length strings' or do the right thing and just allocate memory...
 

PureBasic 4.00

Pre 5.50 Purebasic would offer two modes: Unicode and Ascii. In Ascii mode the string "ABC" would occupy 4 byes, 1 for each character, and a terminating zero:

text  A   B   C   0
hex   $41 $42 $43 $00
dec   65  66  67  0
In Unicode mode, all characters in memory occupy TWO bytes each, plus two terminating zeroes. For simplicty this would look something like this:
text    A       B       C       0
hex  $41 $00 $42 $00 $43 $00 $00 $00
dec   65  00  66  00  67  0   0   0
In other words, eacht character in a Unicode string occupies two bytes, and ends on a pair of two zeroes.

As of v4.00 there is a new type of string, the fixed length string, as well as a single character a sort of 'string companion / byte alternative' called char or .c.

a.s = "this is a test"           ; variable size, zero terminated, cannot contain null characters
b.s{5} = "this is a test"        ; fixed size, can contain null characters, note the type of brackets used!


PureBasic 5.50

Fixed length strings are expecially useful in certain structures and when calling external code libraries. (Those that dealt with old ISDN / TAPI / CAPI know what I mean.) The use of fixed length strings in structures may have been reduced now PureBasic no longer supports Ascii only strings, invalidating stuch structures, but they still have one use: when part of a structure, the string data is stored inside the memory space used by that structure, whilst a normal string would be a pointer towards the string data instead of the data itself.


Booleans

There is no boolean type. Instead, use an integer: 0 is false, <> 0 is true.
 

PureBasic 5.11

As of 5.11 there's the new command Bool(). It returns #True or #False, depending on the expression:

; survival guide 1_5_102 booleans
; pb 5.11
;
OpenConsole()
;
#True = 1
#False = 0
;
a.l = 1
If a
  PrintN("true")
EndIf
;
a.l = #True
If a = #True
  PrintN("true")
EndIf
;
If Bool(a=1)
  PrintN("true")
EndIf
;
Repeat
Until Inkey() <> ""
Life wouldn't be great if we couldn't say no :-) So there's NOT and it's boolean brethern to help us out.

a = (a = b) does not work. Don't even try or ask for it. Don't. Please. Don't. Ask. Ever. PureBasic is not C or C++. It just won't work. Don't ask for it. Please.

If you're a beginner you shouldn't be here at all! Please continue with the primer first and do not hang around here!

Still here? Well, you've asked for it...


Structs aka structures

If a regular string is a member of a structure, then the structure itself does not contain the actual string but a pointer to that string. If you want the string to be part of the structure, you have to use fixed length strings.

; survival guide 1_5_103 structures
; pb 5.50
;
Structure tree           ; this structure is 8 bytes long in 32 bits mode
  a.i                    ; 4 bytes in 32 bits mode, 8 bytes in 64 bits mode
  b.s                    ; 4 bytes in 32 bits mode, 8 bytes in 64 bits mode
EndStructure
;
apple.tree               ; the variable apple is now a structure of type tree
apple\a = 1
apple\b = "this is a test"
;
Debug SizeOf(apple)      ; total structure length will be either 8 or 16 bytes
If you want to have a 'fixed length' string as part of a struct, you either create an array of chars (that sounds a little like c++), or use a fixed length string.

Here's how to do it with an array of chars. The show() procedure shows how this is stored into actual memory:

; survival guide 1_5_104 array of chars
; pb 5.50
;
Procedure show(address.i, size.i)
  Protected hex.s                   ; used to store hex values
  Protected txt.s                   ; used to store text characters
  ;
  n = 0
  While n < size
    byte = PeekA(address+n)
    hex = hex+" $"+Hex(byte)
    If byte >= ' ' And byte <= 'z'
      txt = txt+""+Chr(byte)
    Else
      txt = txt+"*"
    EndIf
    n = n+1
  Wend
  Debug hex
  Debug txt
EndProcedure
;
Structure tree                      ; this structure is 32 bytes long
  y.c[16]                           ; and here are 16 chars ie. 32 bytes
EndStructure
;
apple.tree                          ; the variable apple is now a structure of type tree
Debug SizeOf(apple)                 ; verify its length
;
PokeS(@apple\y,"test",-1,#PB_Ascii) ; pokes() writes 5 bytes, ie. 4 characters plus a terminating zero
show(@apple,SizeOf(apple))
;
PokeS(@apple\y,"test")              ; pokes() writes 10 bytes, ie. 4 characters plus a terminating pair of zeroes
show(@apple,SizeOf(apple))
You could replace an array of chars with a twice as large array of bytes, ie. replace y.c[16] with y.b[32].

An alternative would be to use a fixed length string:

; survival guide 1_5_105 array of chars
; pb 5.50
;
Procedure show(address.i, size.i)
  Protected hex.s                   ; used to store hex values
  Protected txt.s                   ; used to store text characters
  ;
  n = 0
  While n < size
    byte = PeekA(address+n)
    hex = hex+" $"+Hex(byte)
    If byte >= ' ' And byte <= 'z'
      txt = txt+""+Chr(byte)
    Else
      txt = txt+"*"
    EndIf
    n = n+1
  Wend
  Debug hex
  Debug txt
EndProcedure
;
Structure tree                      ; this structure is 32 bytes long
  y.s{16}                           ; and here are 16 chars ie. 32 bytes
EndStructure
;
apple.tree                          ; the variable apple is now a structure of type tree
Debug SizeOf(apple)                 ; verify its length
;
PokeS(@apple\y,"testttt")           ; pokes() writes 10 bytes, ie. 4 characters plus a terminating pair of zeroes
show(@apple,SizeOf(apple))
;
apple\y = "test"                    ; directly storing the string zeroes all unused character positions
show(@apple,SizeOf(apple))


Follow these links for more on structures, pointers inside structures, arrays inside structures and regular arrays...


Expression evaluation

Sometimes Pure does things in its own way. One of these things is the way expressions are evaluated, for example...

a.l = 2/3 + 2/3
Debug a.l                ; will report zero!
;
c.l = 0.6 + 0.6
Debug c.l                ; will report one!
;
x.f = 2/3
y.f = 2/3
b.l = x.f + y.f
Debug b.l                ; will report one!
Surprised? Find out in detail what happens right here...


1.6 Winapi calls
 

Make life easier

This is advanced stuff. Skip it if you're not into this (yet)...
 

Windows XP, Vista, 7, 8

1. First, did you install the WIN32.HLP file? Do so!
2. Okay, now in the editor, type: socket_ and hit F1
3. A window will pop up with details on the windows function. Cool huh?

A lot of standard windows functions are declared. Use the windows function name, add an underscore at the end of the name and try it!

If PureBasic knows the function, it will automatically open the appropriate dll and you don't have to use the OpenLibrary() function. (Even if the editor doesn't recognize the api, the compiler often does. Try to use it, and if there's an error then open the library (DLL) yourself.

The demo version does not support Winapi calls.
 

Windows 10

It's no longer possible to use .HLP files, but, of course, WINAPI calls still work.
 

Type forcing

In PureBasic on 32bit windows you don't have to force the type when calling a Winapi function. (In fact, you cannot even force the type in PureBasic.) So, when the function in WIN32.HLP tells you that the first parameter is a word, you don't bother and just pass it an integer ( or a quad, long, word, or byte) as you feel fit. Same goes for returning values, although obviously they have to fit.


Opening other DLL's

A DLL that is not defined by PureBasic has to be opened by hand. Here's what you do:

1. Open the library using OpenLibrary().

ws_winsock_h.i = OpenLibrary(ws_winsock_pbh,"WSOCK32.DLL")  ;  load the DLL and get back the DLL handle
2. Look for the function you need with GetFunction()...
*ws_wsastartup = GetFunction(ws_winsock_pbh,"WSAStartup")  ;  find the address of the function
3. GetFunction() returned an address. Use that address as a parameter for CallFunctionFast() and pass the appropriate parameters.
ws_retval.i = CallFunctionFast(*ws_wsastartup,$101,@ws_wsadata)
All together now:
ws_wsadata.WSADATA                                                 ; prepare a structure
ws_winsock_h.i = OpenLibrary(ws_winsock_pbh,"WSOCK32.DLL")         ; load the DLL and get back the DLL handle
*ws_wsastartup = GetFunction(ws_winsock_pbh,"WSAStartup")          ; find the address of the function
ws_retval.i    = CallFunctionFast(*ws_wsastartup,$101,@ws_wsadata) ; call the function by its address
The code above is only to illustrate the approach. Don't forget to close the library before ending your program. An alternative way is using CallFunction() or by using function pointers / prototypes. See here for more details.


1.7 Other
 

Former GfaBasic users look here... some of those things might be of interest to people used to other dialects as well.


1.8 My (stupid) questions

Over time I have asked some (stupid) questions regarding PureBasic... or witnessed those of others :-) Here are some of the answers that *might* be useful to you...

Q. I've seen a cheaper version on the internet!

A. Quite possible. PureBasic was available in other (boxed) versions as well, but only the 'expensive' version gets the lifetime free updates. All the 'boxed' 'editions' are worthy of some suspicion, so check on purebasic.com and the forums before buying anything! (In fact, there's no reason whatsoever to buy such a box, as those are old versions without a right to upgrade.)
Q. Where can I find a list of all PB constants?
A.Open the structure viewer (from the tools menu in the editor) and select the constants tab.
Q. And Windows constants?
A. Look around on the internet, there should be enough lists and utilities floating around... The Windows SDK is one option.
Q. Nice, those files with all the constants, but they are very large and load slowly. Or I can't even read them...
A. Go to the Total Commander site and download lister.exe. In the standard editor you can add your own tools / config tools. Use path+lister.exe in the command line and path+filename for the file you want to view. Lister is fast and smart. And, while you are on the Total Commander site... register it. It's worth it. This shameless plug doesn't make me any money... (No money again? Damn!) 
Q. So, PureBasic has loads of constants pre-defined... and structures too... or not?
A. How right you are. Browse through those files with constants, and you'll run into the structures as well. But, PureBasic offers you a nice boon. Hit [Alt] + [S] and you can browse through all predefined structures, including their fields. That will save you quite some time. (There were a few errors in the default structs though so check them before using them.)
Q. What's an unsigned short?
A. A word. (Yes, I know, this is not entirely true. Don't bother.)
Q. Why can't I find EventWParam() in the help file?
A. It's a command that's Windows specific and might disappear one day. Although it's not very likely it will disappear anytime soon so don't worry too much :-)
Q. How can I check if a file exists?
A. Use the FileSize() function (it was listed in the newbies faq, and I still asked the question, yes, I'm thick too)...
Q. Why does <whatever> not work?
A. Check out the FAQ on the forum, and do a search there.
Q. Why does a = (a = b) not work?
A. PureBasic isn't C++. It just doesn't work. Don't even try or ask for it.


a = (a = b) does not work. Don't even try or ask for it. Don't. Please. Don't. Ask. Ever. PureBasic is not C or C++. It just won't work. Don't ask for it. Please.
 

There are tons of questions and answers to be found on the forum... Make sure you read the faq and do a search on that forum before posting a question! (Fortunately, it's a very understanding community, hum :-) Just remember, the best answers are those you found yourself... Also the Primer may just address that one stupid question you were always afraid to ask...


1.9 Some sample code

Many samples can be found on the PureBasic forum, and some more in the code archiv at purearea.net.

Note: please make sure you use the right version of PureBasic, or be prepared for some decent DIY as some of those samples may be quite old!

Still here? Return to the TOC or continue with the Primer.


1.10 Thanks!

... to AlphaSnd / Fred, Fr34k / Freak, GPI, Inner, Pupil, Rings, Saboteur, TerryHough, TheFool, WolfgangS, and all those other people I forgot to mention...