Thursday, July 4, 2019

Delphi and C++Builder Version Chart

I created this extended product version chart, because I cannot seem to access this information elsewhere and I often need it when resolving component install issues (to reference folder and registry locations between versions)

Company Product Product Version Package Version Compiler Version IFDEF Version BDS Version
Borland Delphi 1 1  -  - VER80  -
Borland Delphi 2 2  -  - VER90  -
Borland C++Builder 3 3  -  - VER110  -
Borland Delphi 3 3  -  - VER100  -
Borland C++Builder 4 4  -  - VER125  -
Borland Delphi 4 4  -  - VER120  -
Borland Delphi/CPB 5 5  -  - VER130  -
Borland Delphi/CPB 6 6 60 14.0 VER140  -
Borland Delphi 7 7 70 15.0 VER150  -
Borland Delphi 2005 9 90 17.0 VER170 3.0
Borland Delphi/CPB 2006 10 100 18.0 VER180 4.0
Borland Delphi/CPB 2007 11 110 18.5 VER185 5.0
CodeGear Delphi/CPB 2009 12 120 20.0 VER200 6.0
CodeGear Delphi/CPB 2010 14 140 21.0 VER210 7.0
Embarcadero Delphi/CPB XE 15 150 22.0 VER220 8.0
Embarcadero Delphi/CPB XE2 * 16 161 23.0 VER230 9.0
Embarcadero Delphi/CPB XE3 * 17 170 24.0 VER240 10.0
Embarcadero Delphi/CPB XE4 * 18 180 25.0 VER250 11.0
Embarcadero Delphi/CPB XE5 * 19 190 26.0 VER260 12.0
Embarcadero Delphi/CPB XE6 * 20 200 27.0 VER270 14.0
Embarcadero Delphi/CPB XE7 * 21 210 28.0 VER280 15.0
Embarcadero Delphi/CPB XE8 * 22 220 29.0 VER290 16.0
Embarcadero Delphi/CPB 10 Seattle * 23 230 30.0 VER300 17.0
Embarcadero Delphi/CPB 10.1 Berlin * 24 240 31.0 VER310 18.0
Embarcadero Delphi/CPB 10.2 Tokyo * 25 250 32.0 VER320 19.0
Embarcadero Delphi/CPB 10.3 Rio * 26 260 33.0 VER330 20.0

* 64bit Support

Also see: http://docwiki.embarcadero.com/RADStudio/Rio/en/Compiler_Versions

Wednesday, July 3, 2019

Different function parameter modifiers in Delphi - Ali Keshavarz

(Useful article that was originally posted on now defunct vcldeveloper.com)

Recently a friend asked me about constant parameters in Delphi functions, that brought the idea of writing a new post about passing parameters to functions/procedures in Delphi.

 

Parameter modifiers

When you call a function or procedure (I am going to refer to both of them as Functions here), you have to somehow pass the required input or output parameters to it. Parameters are passed to functions either by value, or by reference.

Passing by value means, compiler makes a new copy of the original data, and sends it to the function. This way, the function has its own copy of data, and changing value of the parameter inside the function does not affect the original data. This is the default mode when you pass a parameter to a function in Delphi:

program Test02;
procedure Foo(Param1: Integer);
begin
  Inc(Param1); //=> Has no effect on MyData.
end;
var
  MyData : Integer;
begin
  MyData := 1;
  Foo(MyData);
  Writeln(MyData); //=> MyData is still 1.
end.

Passing by reference means, compiler only sends a pointer to the function. This pointer refers to the original data, so changing value of the parameter inside the function directly changes the original data. In Delphi such parameters are marked with var keyword:

program Test02;
procedure Foo(Var Param1: Integer);
begin
  Inc(Param1);
end;
var
  MyData : Integer;
begin
  MyData := 1;
  Foo(MyData);
  Writeln(MyData); //=> MyData is 2.
end.

These are the two basic ways parameters are passed to functions, but Delphi has still two other modifier keywords for function parameters: const and out. What are these two used for?
“Const” makes the parameter read-only, so that you cannot change its value inside the function. This lets compiler to generate optimized code when there is no need to alter value of that parameter inside the function.

procedure Foo(const Param1: Integer);
begin
  Inc(Param1); // ERROR! You cannot modify a const parameter.
end;

“Out” is similar to “var”, the difference is, when you use “Out” the initial value of the parameter is discarded inside the function, and it does not matter. What matters is the value you assign to that parameter inside your function. “Out” is basically there to support MS COM method declaration in Delphi. You can use it in any function you write, but you will see lots of COM methods having Out parameters in their declaration.

OK, the purpose of Const and Out modifiers are clear, it can be guessed even from their name which represent Constant and Output; but, to which category do they belong?

 

Are “Out” and “Const” passed by value or by reference?

For “out”, as I mentioned above, it acts similar to “var”, so it passes parameters by reference.
How about “Const’? Const acts somehow differently! It passes parameters usually by value, but it passes certain data types by reference too! Which data types are passed by value, and which ones are passed by reference? To clarify this, I wrote a simple program; it shows address of a parameter passed to a function using the default passing (by value), var modifier (by reference), and const modifier. It repeats this for various data types, to show how these modifiers pass different data types to a function. The source code is attached at the end of this post. Here is a screenshot of this sample program:





For each data type, “Original:” line indicates address of the original data before being passed to the function. “Value:” line indicates address of the parameter passed to the function by value. “Const:” line indicates address of the parameter passed to the function as a constant. And finally, “var:” line indicates address of the parameter passed to the function by reference.
As you can see, for all data types, address of var parameter is the same as address of the original data, and address of value parameter (passed by value) differs from the original data. Therefore, we can conclude passing a parameter by value, always makes a copy of the original data; and passing a parameter with var modifier always refers to the original data, regardless of the data type which is used.

But for constant parameters, we can see that it always passes the parameter by value, except when the parameter is of array type (static arrays and open arrays, not dynamic arrays; dynamic arrays are passed similar to objects), or record type. It means, if you do not specify a modifier for a parameter of type array (not dynamic arrays) or records, then every time your function is called, the whole data inside that array or record will be pushed into stack, and when the execution of your function is over, it is dismissed! On the other hand, when you use Const or Var modifiers, only a pointer to your record or array is passed to the function, so there is no need to copy the whole data of the array or record.
Now you might ask, if the compiler is smart enough to optimize array and record parameters when Var or Const modifiers are used, then why doesn’t it use the same optimization for objects, interfaces, strings, or dynamic arrays?! The answer is: Because those are special data types!


Objects, Interfaces, Strings, and Dynamic Arrays as parameters

Objects, interfaces, strings, and dynamic arrays are behind the scene just pointers. They do not contain the real data. They are pointers that refer to the real data. That’s why if you call SizeOf() function on a string or object type, even if your string or object contains huge data; the result is always 4 (as long as Delphi compiler is 32-bits)! SizeOf() function only returns the size of that pointer, not size of the data that pointer refers to. Also that is why we have Length() function for getting size of strings and dynamic arrays, and TObject.InstanceSize class method for getting size of an object.
Hence, for data types as objects, interfaces, strings, or dynamic arrays; we can say practically they are always passed by reference, even if no modifier is specified for them. So the code bellow directly affects StringList variable, and there is no local copy of that object inside Foo:

program Test03
uses Classes;
procedure Foo(Param1: TStrings);
begin
  Param1.Add(‘۱۲۳۴’); //=> This will directly add a new item to StringList.
end;
var
  StringList : TStringList;
begin
  StringList : TStringList.Create;
  try
    Foo(StringList);
    WriteLn(StringList.Text); //=> Writes ‘۱۲۳۴’.
  finally
    StringList.Free;
  end;
end.

Using var modifier on objects, interfaces or dynamic arrays is most of the time unnecessary, because the value itself is a reference, so using var means having a reference to another reference!
Also Const modifier has no particular meaning on objects, interfaces or dynamic arrays, because it only locks the pointer behind the scene, not the data structure to which the pointer is referring. So if we change declaration of Foo() in the code above to this:

procedure Foo(const Param1: TStrings);
We will get the same result as the above code.

However, const and var modifiers have meaning for string types! This is because strings are a special auto-managed data types in Delphi.


Strings, Dynamic Arrays, and Interfaces are referenced counted:

Strings and dynamic arrays are both reference-counted. Interfaces in Delphi also provide reference-counting support). Reference-counted types are automatically handled by Delphi runtime. When you define a string variable in Delphi and assign it a value, you will have a data structure containing your text, and a reference-counter value which is set to 1:

var
 A : string;
begin
  A := ‘Test’; // Memory is allocated for A
                  // on the heap, and reference
                  // counter is set to 1.
end;

Now if you change the above code to this:

var
  A, B : string;
begin
  A := ‘Test’; // Memory is allocated for A
                  // on the heap, and reference
                  // counter is set to 1.
  B := A;      // Reference count for the data
                 // structure referred by A is incremented to 2.
end;

Value of A is not copied to B, instead of that, B refers to the same data structure as A, and reference counter of that data structure is set to 2. As soon as any of those variables goes out of scope, reference counter of that data structure would be decremented, and when reference counter reaches down to zero, the data structure would be automatically freed. This mechanism is the same for strings and dynamic arrays. For interfaces, the class which implements the interface should implement three methods defined inside IInterface to provide reference-counting support.

Strings use Copy-On-Write technique:

The biggest reason why Const and Var modifiers are meaningful to string types is their copy-on-write feature. To explain this, I had to explain reference-counting in brief. Now please take a look at this example:

var
  A, B : string;
begin
  A := ‘Test’; // Memory is allocated for A
                  // on the heap, and reference
                  // counter is set to 1.
  B := A;      // Reference count for the data
                 // structure referred by A is incremented to 2.
  B := B + ‘er’;   // B = Tester , A = Test
end;

This is the same as the previous sample code, with one extra line. In the last line, we add ‘er’ to variable B. That will result in B referring to “Tester”, not “Test” anymore. How is it done? A and B were both referring to a data structure containing “Test”. Then we decided to modify B. Delphi runtime assigns a new data structure, and copies the string “Test” and the string “er” to it. It also decrements reference-counter of original “Test”, and changes B to refer to the new data structure. It also increments reference-counter of the new data structure. So at the end, we have A which refers to the old data structure, and B which refers to the new data structure. Reference-counters of both data structures are 1 now.

This is called copy-on-write; as long as there is no modification, there is no need to do the costly copy operation and waste the memory. Delphi waits until a modification is requested, at that time, it does the actual copy operation.

Please take note, this mechanism does not exist for dynamic arrays, so if A and B in the code above were dynamic arrays, changing B would have affected A too.


So, how does a string parameter work?

When a string parameter is defined with no modifier, it is sent to the function as a reference to the actual data, but its reference-counter would be incremented when entering the function, and decremented when exiting the function. If a modification is done on the string parameter, then a new local string variable would be created inside the function, and the original value of the parameter would be copied to it (Copy-on-write operation). The change would be reflected on the local string variable. This local string variable would be released when execution of the function is over.
When a string parameter is defined as a constant, compiler is sure that the string cannot be modified inside the function, therefore, there is no need for it to add codes for automatic incrementing and decrementing of the reference-counter.
When a string parameter is defined with var modifier, then it is sent to the function as a reference to the actual data. When value of the parameter is changed, then the original data would be copied to a new memory location, and the modification would be applied to it in the new memory location:

program Test04;
procedure Test(var Param: string);
begin
  Param := Param + Param;
end;
var
  A, B : string;
begin
  A := 'Test';
  B := A;
  Test(A);
  Writeln(A); //=> A is modifed and is now “TestTest”
  Writeln(B); //=> B still refers to “Test”
end.
Now back to the original question:


When should we use Const modifier for parameters?

  1. Whenever you have a parameter of type array or record, and you do not need to modify it inside your function; define it as a constant parameter to prevent expensive copy operation of array elements every time your function is called.
  2. Whenever you have a parameter of type string or dynamic array, and you do not need to modify it inside your function, define it as a constant parameter to prevent compiler from generating protecting code to keep track of the reference-counter. When you do not use const modifier in such cases, compiler would add a hidden try-finally block to your function which contains code for keeping track of reference-counter for your string or dynamic array parameter. This would affect performance of your code. To read more about the impact of this, and see how much code compiler would produce in that case, you can read Eric Grange’s post on this.
Important Note: For the second recommendation above to work, you have to set “String format checking” in your project option to False. This option adds that protective try-finally block to your functions whether you define your string or dynamic array as const or not! This is for backward compatibility with some old C++ Builder codes. If you are not a C++ Builder developer, or are a C++ Builder developer, but do not have such old codes, then you MUST set this option to False in your projects. It reduces performance of strings in Delphi.



OK, I hope this post is clarifying function parameter modifiers and their effects in Delphi programming; specially answering the question of when to use Const modifier.

Have Fun!

Tuesday, June 11, 2019

Five FireDac Image Demos and more in ImageEn v8.6.0

We have now released ImageEn 8.6.0, which overhauls database support, including five new database demos using FireDac.



Other Enhancements

1. New TIEAngleLayer to display and measure angles within an image


2. TImageEnMView and descendents now allow in-place editing, including file renaming in TImageEnFolderMView and layer renaming in TImageEnLayerMView



3. Many improvements to database functionality, including use of TIEDBMultiBitmap to show multi-frame images at the current database cursor

4. Improved TImageEnFolderMView, including new methods and TActions for to show properties, edit, print file, etc, more keyboard shortcuts, and complete "Windows Explorer"-style demo



5. Enhancements to CaptureFromScreen, including specifying a window to capture

Complete Change History: http://www.imageen.com/info/history.html



ImageEn v8.6.0 is free if you purchased a license or extension after 10 June 2018. 

Download via: http://www.imageen.com/support/downloadrequest.html
Other users can extend at: http://www.imageen.com/order/index.html#Extensions


More Info: http://www.imageen.com/info/

Monday, April 22, 2019

ImageEn 8.5.0 now localized into 13 languages, plus improved brush painting and new FolderTree and FileListBox components

ImageEn v8.5.0 has now been released.This update is free if you purchased a license or extension after 21 April 2018. 

Download via: http://www.imageen.com/support/downloadrequest.html

Other users can extend at: http://www.imageen.com/order/index.html#Extensions


More Info: http://www.imageen.com/info/

 

Top Ten Enhancements

1. Complete translations for 13 languages: Italian, French, German, Russian, Chinese (Simplified and Traditional), Spanish, Portuguese, Arabic, Japanese, Korean, Dutch and Turkish



2. Many improvements to the BrushTool, including support for rotated and asymmetric brushes, and brushes containing transparency



3. Many optimization and new properties for JPEG 2000 support, including support for loading and saving very large images

4. Two new controls: TIEFolderTree, a Windows Explorer style shell TreeView, and TIEFileListBox, a file listbox with native icon support



5. TIELayerMView can now display a layer masking button allowing you to quickly set a layer as a mask



6. TImageEnMView can now browse connected cameras and smart phones

7. Many improvements to Portable Device functionality including retrieval of thumbnails

8. New iemsFilenames display style for TImageEnMView

9. TImageEnView ruler adds support for all standard unit types

10. Stock Icons can be retrieved from Windows

Monday, February 25, 2019

Improved Image Layer Editing and Styling for ImageEn Imaging Library

Also, released today is our v8.3.0 update for ImageEn, the powerful image display, editing and processing component suite for Delphi and C++ Builder.


Top Ten Enhancements in ImageEn 8.3.0

1. All layer types can now be used as masks, so you can easily create stylized text, gradient masks and shaped images
 


2. “New Layer” dialog allows you to configure and style a layer to insert into your image

 


 3. Many WIC improvements, including support for auto-rotation of camera images and meta-data when using Fast Loading via WIC. Also outputs codec information in TIOParams

4. Google’s WebP format is now supported via WIC

5. Updated to the latest Raw library version, and ImageEn now automatically loads Camera Raw files using built-in Windows codecs, if ImageEn’s DLL is not included

6. When outputting a series of images to AVI, you can now include an audio track

7. Styling improvements for TImageEnMView including, Explorer-style hover effect and a color set similar to Windows dark theme (without needing VCL theming)




8. TImageEnLayerMView now allows layers to be excluded, and supports all keyboard shortcuts of TImageEnView



9. New style options for layers include more gradient options, and fills can now be a different opacity from borders and text

10. A set of editing options allow more control over permitted behavior in TIEColorCurve
 

 
 
More Information and Trial Downloads

IEVision implements Tesseract 4 for more accurate OCR in Delphi/C++

We have just released a major update to IEVision, our advanced tools add-in for Delphi and C++ Builder. This update implements Tesseract 4 for more accurate OCR.


Video capture using installed drivers

About IEVision, Advanced Features Add-In

The easiest way to add powerful functionality to ImageEn is with the IEVision add-in:
· OCR: Image to Text Conversion
· Barcode Recognition
· Patching of images (to hide blemishes and copy content)
· Photo Stitching
· Face and object detection and tracking
· Advanced image processing algorithms


More Info and screenshots: http://www.imageen.com/IEVision/
Demos: http://www.imageen.com/demos/index.html#IEVision

Top Five Enhancements in IEVision 5.0.0

1. Now supports Tesseract 4 for much faster and more accurate OCR (Error Reduction Statistics: English: -30%, French: -50%, Spanish: -46%, Russian: -79%, Hebrew: -32%, Chinese: -22%, Korean -79%, etc.)
2. Sixty languages added to OCR, such as: Armenian, Breton, Corsican, Filipino, Gaelic, Mongolian, Maori, Tongan
3. New PDF generation class to create searchable (OCRed) PDF documents from images
4. New OCR properties to detect advanced formatting (Sub/Superscript, dropped caps, etc)
5. Other improvements and fixes

Upgrading to IEVision 5.0.0

Purchase or upgrade IEVision at:

http://www.imageen.com/order/

Monday, November 26, 2018

ImageEn Imaging Library Update for 10.3 Rio (Trial available)


ImageEn v8.1.2 has now been released to add support for Delphi/C++Builder 10.3 Rio.

ImageEn is a powerful native image display, editing and processing library. Learn more at: www.imageen.com

We now have a trial version, which is available via GetIt in the Delphi IDE, or our web site at: www.imageen.com/demos/

There are also 200 pre-compiled demo applications so you can instantly try all our features.

Top Five Enhancements

1. Enhanced TImageEnLayerMView with background layer locking and custom hover hints




2. Layer Properties dialog improvements including drawing of Line End shapes in combobox, plus optional image-only display for all combobox captions




3. Polyline layers can be created from a selection

4. All pages can be previewed when printing posters

5. Full localization support for Russian and Dutch languages

Complete Change History: www.imageen.com/info/history.html


The update is free to all users who purchased a license or extension after 26 November 2017. You can download at: www.imageen.com/support/downloadrequest.html