Porting Delphi code
Porting Delphi code should be quite painless. The Delphi mode of the compiler tries to mimic Delphi as closely as possible. This mode can be enabled using the -Mdelphi command line switch, or by inserting the following code in the sources before the unit or program clause:
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF FPC}
This ensures that the code will still compile with both Delphi and FPC.
Nevertheless, there are some things that will not work. Delphi compatibility is relatively complete up to Delphi 7. New constructs in higher versions of Delphi (notably, the versions that work with .NET) are not supported.
Missing language constructs
At the level of language compatibility, FPC is very compatible with Delphi: it can compile most of FreeCLX, the free Widget library that was shipped with Delphi 6, Delphi 7 and Kylix.
Currently, the only missing language constructs are:
Dynamicmethods are actually the same asvirtual.Constfor a parameter to a procedure does not necessarily mean that the variable or value is passed by reference.Packages are not supported.
There are some inline assembler constructs which are not supported, and since Free Pascalis designed to be platform independent, it is quite unlikely that these constructs will be supported in the future.
Note that the -Mobjfpc mode switch is to a large degree Delphi compatible, but is more strict than Delphi. The most notable differences are:
Parameters or local variables of methods cannot have the same names as properties of the class in which they are implemented.
The address operator is needed when assigning procedural variables (or event handlers).
AnsiStrings are not switched on by default.
Hi/Lo functions in Delphi are always evaluated using a word argument, in FPC there are several overloaded versions of these functions, and therefor the actual type of the passed variable is used to determine which overload is called. This may result in different results.
Missing calls / API incompatibilities
Delphi is heavily bound to Windows. Because of this, it introduced a lot of Windows-isms in the API (e.g. file searching and opening, loading libraries).
Free Pascalwas designed to be portable, so things that are very Windows specific are missing, although the Free Pascalteam tries to minimize this. The following are the main points that should be considered:
By default, Free Pascalgenerates console applications. This means that you must explicitly enable the GUI application type for Windows:
{$APPTYPE GUI}The
Windowsunit provides access to most of the core Win32 API. Some calls may have different parameter lists: instead of declaring a parameter as passed by reference (var), a pointer is used (as in C). For most cases, Free Pascalprovides overloaded versions of such calls.Widestrings. Widestring management is not automatic in Free Pascal, since various platforms have different ways of dealing with widestring encodings and Multi-Byte Character Sets. FPC supports Widestrings, but may not use the same encoding as on Windows.
Note that in order to have correct widestring management, you need to include the
cwstringunit on Unix/Linuxplatforms: This unit initializes the widestring manager with the necessary callbacks which use the C library to implement all needed widestring functionality.Threads: At this moment, Free Pascaldoes not offer native thread management on all platforms; on Unix, linking to the C library is needed to provide thread management in an FPC application. This means that a
cthreadsunit must be included to enable threads.A much-quoted example is the
SetLastOSErrorcall. This is not supported, and will never be supported.Filename Case sensitivity: Pascal is a case-insensitive language, so the uses clause should also be case insensitive. Free Pascal ensures case insensitive filenames by also searching for a lowercase version of the file. Kylix does not do this, so this could create problems if two differently cased versions of the same filename are in the path.
RTTI is NOT stored in the same way as for Delphi. The format is mostly compatible, but may differ. This should not be a problem if the API of the TypeInfo unit is used and no direct access to the RTTI information is attempted.
By default, sets are of different size than in Delphi, but set size can be specified using directives or command line switches.
Likewise, by default enumeration types are of different size than in Delphi. Here again, the size can be specified using directives or command line switches.
In general, one should not make assumptions about the internal structure of complex types such as records, objects, classes and their associated structure. For example, the VMT table layout is different, the alignment of fields in a record may be different, etc.
The same is true for basic types: on other processors the high and low bytes of a word or integer may not be at the same location as on an Intel processor (the endianness is different).
Names of local variables and method arguments are not allowed to match the name of a property or field of the class: this is bad practise, as there can be confusion as to which of the two is meant.
Delphi compatibility mode
Switching on Dephi compatibility mode has the following effect:
Support for Classes, exceptions and threadvars is enabled.
The
objpasis loaded as the first unit. This unit redefines some basic types:Integeris 32-bit for instance.The address operator (@) is no longer needed to set event handlers (i.e. assign to procedural variables or properties).
Names of local variables and method parameters in classes can match the name of properties or field of the class.
The
Stringkeyword impliesAnsiStringby default.Operator overloading is switched off.
Best practices for porting
When encountering differences in Delphi/FPC calls, the best thing to do is not to insert IFDEF statements whenever a difference is encountered, but to create a separate unit which is only used when compiling with FPC. The missing/incompatible calls can then be implemented in that unit. This will keep the code more readable and easier to maintain.
If a language construct difference is found, then the Free Pascalteam should be contacted and a bug should be reported.
An experiment, built from development snapshots. Not the official Free Pascal or Lazarus documentation.
