2022-03-04
md
Free Pascal/Lazarus Gotchas
Free Pascal/Lazarus TThread Gotchas->

In my experience, moving from Delphi to Lazarus is mostly painless, and in some respects quite enjoyable. But there are small differences that can be the source of some head scratching. Here are some "gotchas" that have tricked me in the past and sometimes still trip me up.

Table of Contents

  1. Assigning Procedural Variables in objfpc Mode
  2. Recursion in objfpc Mode
  3. Assigning Procedural Variables at Run-Time in objfpc Mode
  4. No Debug and Release Build Modes
  5. Demonstration Program

Assigning Procedural Variable in objfpc Mode toc

Procedural variables must be assigned with the address operator @ in fpc and objfpc modes. This is clearly indicated in the Free Pascal Programmer's Guide: D.1 FPC mode and D.5 OBJFPC mode. The operator is not necessary in delphi or tp (Turbo Pascal 7) mode. Object event handler variables are procedural variables so the same applies to them. However in that case, the error message Error: Wrong number of parameters specified for call to "EditChange" often confuses me and sends me on a wild goose chase counting parameters and wondering why there is a problem. After all, the handler EditChange has exactly one parameter as expected of a TNotifyEvent handler.

Recursion in objfpc Mode toc

A function without parameters will not call itself recursively unless parenthesis are appended to the function name :

function myFunction: integer; begin ... result := 32 * myFunction(); // don’t forget the ()! ... end;

This C style calling convention is not necessary in Delphi and is not necessary in a Free Pascal program if delphi mode ({$mode delphi}, not case sensitive) is used instead of the default {$mode objfpc}.

Assigning Procedural Variable at run-time in objfpc Mode toc

This is pretty much the same gotcha as above. If a procedure type is defined for functions without parameters, is will be necessary to append parenthesis to the procedural variable to invoke the function in objfpc mode.

type TFunctionType = function: integer; var aFunction: TFunctionType; begin aFunction := @recur2; Label1.Caption := 'recur2 = ' + inttostr(aFunction());// Don't forget the ()!

No Debug and Release Build Modes toc

Debug and release build modes are not defined by default in a new project. However, they are easily created by checking the Build modes in Options for MyProject. You can get to that window in the Lazarus IDE by selecting the following menu choices: Project / Project Options ... / Compiler Options. A Build Mode window will appear. Click on the Create Debug and Release modes button to add these two build modes to the Default mode.

Even when these modes are enabled, the DEBUG and RELEASE symbols not defined in corresponding build modes. To add these symbols, click on the Custom Options choice in the CompilerOptions (see above). Then click on the Defines... button and add the two symbols DEBUG and RELEASE. Close the Defines window by clicking on the Ok button and the select the Debug mode in the build mode combo box at the top. Click on the Defines... button again and check the DEBUG symbol and uncheck the RELEASE symbol if necessary and click on the Ok button. The Custom options memo should then show -dDEBUG. Select the Release build mode and click on Defines... and this time check the RELEASE and uncheck the DEBUG symbols. Then -dRELEASE should appear in the Custom options memo once the Defines window is closed.

This procedure is valid for Lazarus version 1.6. You could probably add the -dDEBUG and -dRELEASE defines directly in the custom options memo. I seem to recall that was how it was done in version 1.4.

Demonstration Program toc

The archive gotcha.zip contains a small program illustrating these problems and solutions. Be sure to run the program four times, once with the directive {$mode objfpc} defined and {$mode delphi} undefined and again inverting these defines in Unit1.pas and then again in Unit2.pas. The debug and release build modes are defined in this project along with the corresponding DEBUG and RELEASE directives.

Free Pascal/Lazarus TThread Gotchas->