marco
cantu

Books : Mastering Borland Delphi 2005: Update for Delphi 2006

Mastering Delphi Update for Delphi 2006


Chapter 4

The Win32 compiler in Delphi 2006

As mentioned in the update material for the last chapter, in Delphi 2006 the Delphi compiler for Win32 has been extended to correspond more closely to the its .NET counterpart. These new features are described in the add-on for Chapter 4 because it is in Chapter 4 of “Mastering Borland Delphi 2005” that they were already introduced for .NET.

Class Instance Fields in Win32

In Delphi 2006, even the Win32 compiler, like the .NET one, supports the usage of class instance fields (or class variables) and of class properties mapped onto those fields, exactly as I describe in the section “Class Data and Class Static Members” (page 131) in the printed book. The syntax used by the compiler is the same: class var.

Notice that this declaration can be followed by one or more class variable declarations. To get back to the declaration of other instance fields, you can write a var declaration (something not commonly used in the past):

type

  TMyData = class

  private

    class var

      CommonCount: Integer;

      OtherClassVar: string;

    var

      StandardField: Integer;

Records with Methods and Operators Overloading

A similar upgrade in the Win32 compiler took place with two other features already in the .NET version; now the language is now identical for the two compilers in these aspects.

The first of these new features is the possibility of adding methods to records. The rule is that you can add only non-virtual methods, as records inheritance is not supported in Win32. You can also define a pseudo-constructor to initialize the data, but you cannot have a destructor.

The key difference between records and classes is the way they are allocated in memory. Variables having a class as type are allocated dynamically: in this case a variable is a reference to the actual memory location of the object. Variables with a record as type are allocated locally, either on the stack (for local method variables), within the containing object (for class fields), or in the global memory (for global variables). The differences in memory allocation can cause some significant differences in the processing time (generally favoring records) and in the amount of memory used (often favoring classes). The speed difference is demonstrated in the Win32 version of the RecordsDemo example, described in the section “Records or Classes” of the printed book.

The second new feature relates to operator overloading. While in .NET (at least in theory) this is supported by both classes and records, in Win32 this feature is limited to records only. In fact, the automatic creation of new result objects in Win32 will cause severe memory leaks (while in .NET the garbage collection gets rid of the problem). Beside this difference, definition and usage of operators is the same of the .NET version of the language, described in the section “Operators Gain New Ground” (page 146).

Speaking of records, the language has also been extended in Delphi 2006 to support the definition of record helpers that allow you to add methods to an existing record, exactly as with class helpers.

Class Helper

Class helpers have now been formally introduced in the Win32 compiler. In Delphi 2005 class helpers were not formally available, and although you could use them they were actually quite buggy. It was quite easy to get internal compiler errors while using them, nothing you could complain to with Borland about as this feature was not officially supported.

There isn't that much to say about class helpers. Their capabilities have been described in the section “Class Helper” of the printed book for the .NET version and their Win32 counterpart are indeed identical. The example ClassHelpersWin32 already compiled and worked in Win32 for Delphi 2005 (although making even small changes to the code might result into internal errors). Now everything works and you get proper error messages if you type something incorrect.

However, unlike with the .NET compiler, there is very little reason for using class helpers with the Win32 compiler. There might be cases you want to extend an existing library class or record without touching it and without using inheritance, but there are often cleaner coding solutions (like writing a wrapper class or some global support functions) not based on class and record helpers.

Delphi for .NET Compiler and the Compact Framework in Delphi 2006

The Delphi for .NET compiler hasn't seen any significant change or improvements in the language (many new features are expected in the next version of Delphi, that is going to support version 2.0 of the .NET framework). The specific new feature is the full support in the Delphi 2006 .NET compiler for the .NET Compact Framework (CF). This gives the ability to produce executables that run on the Pocket PC devices, the hand-held devices using the latest version of the Microsoft Windows CE operating system.

A few months after the release of the Delphi 2005, Borland made available a Preview of the Delphi for .NET compiler for the CF platform, that could be used only from the command line. Now this capability is built into the core compiler, so that it can be used from the IDE. You don't even need a specific compiler setting or option: the application you produce is directly capable of running on a PocketPC device, provided this has the .NET runtime installed.

To build a CF application you need to link your program to the CF version of the .NET assemblies, which are a subset (compact version) of the full .NET assemblies. The .dcpil interface files for the CF assemblies is already available in the <BDS>\lib\cf folder. Refer to this folder in your search path, from the Directories/Conditionals section of the project option, and you are set to go. No defines, no compiler settings, nothing else.

You don't even need to refer to the proper assemblies in the Requires section of the project, in the Project manager. Even if this refers to the full library the linker and the Code Insight engine will use the reference to the proper assemblies from the project configuration.

As I mentioned, the compiler has no specific flag. There is no difference in the generated code, only you cannot refer to symbols (classes, methods) not available on the reduced framework. However, you might need to have some sort of IFDEF mechanism, so that the same unit compiled in a CF project or a standard done will have extra or different code. In such a case, the standard approach is to follow what Borland is doing in the Delphi RTL for .NET (which now support the CF platform as well). What Borland does is to add a conditional define based on the presence of a given symbol of the library:

// in a shared unit

{$IF NOT DECLARED(System.AppDomain.CurrentDomain.ProcessExit)}

  {$DEFINE CF}

{$IFEND}

// where you need conditional code

{$IFDEF CF}

  // CF specific code...

{$ENDIF}

Delphi 2006 support for the CF platform is limited to the compiler and a few extended RTL libraries (like Borland.Delphi.System, Borland.VCL.SysUtils, and the like). There is no visual designer and the WinForm design of the IDE (which is the one part of the .NET SDK licensed by Borland) produces many statements unavailable on the CF platform. For the moment, you have to use some specific plug-in tools or manually edit the designer-generated code.