Pascal Programming

Entries feed - Comments feed

2012-05-20

Recursive calls and private objects

In a Stack Overflow question, someone asked about some nested procedure call he found out. That is, a procedure inside another procedure.

He found out this coding style to be messy, which sounds like a reasonable opinion. But his alternative proposal of putting the internal procedure outside the main one, i.e. making it global, is IMHO even worse.

In some case, a private class, or even record or object with methods is an handy and maintainable implementation pattern.

Continue reading

2012-04-19

Smart: mORMot, from Delphi to JavaScript

Did you hear from the great Smart project?

It is an IDE and some source runtime able to develop and compile an Object-Pascal project into a HTML 5 / CSS 3 / JavaScript embedded application.
It does target AJAX Mobile application creation (i.e. Android and iPhone/iPad apps running Web-Kit).
You'll get an unique .html file containing the whole client-side application: it won't need any server side implementation. Using a third-party tool like PhoneGap, you'd be able to supply your customers with true native applications, running without any network, and accessing the full power of any modern Smart Phone.

Smart is a great candidate for implementing rich client-side AJAX applications, to work with our client-server mORMot framework.

In order to interface Smart code with mORMot, we started implementing some low-level code to work with our RESTful authentication scheme.

So we'll need to implement some Smart dedicated Open Source code implementing crc32 and SHA-256 hashing.

Continue reading

2012-04-10

How function results are allocated

One potential issue with Delphi coding, is about how the result of a functions are implemented.

If you forget to set a result value to a function, you'll get a compiler warning.
Never underestimate such warning: IMHO this is not a warning, but an error.

And you should better be aware of the handling of reference-counted types (e.g. string) in a function results: those are passed the stack as var parameters, so the result of a function may be set even if an exception is raised during function execution!

Continue reading

2012-02-29

Delphi and interfaces

No, interface(-book) is not another social network, sorry.

In Delphi OOP model, an interface defines a type that comprises abstract virtual methods.
The short, easy definition is that an interface is a declaration of functionality without an implementation of that functionality. It defines "what" is available, not "how" it is made available. This is the so called "abstraction" benefit of interfaces (there are another benefits, like orthogonality of interfaces to classes, but we'll see it later).

In its upcoming 1.16 revision, our mORMot framework is able to use interface for its service definition.

So we'll discuss and introduce this gem available in all modern languages - including Delphi: interfaces.

Continue reading

2012-02-09

Using SetLength or SetString

Some Delphi users even do not know the existence of the SetString function.

As stated by the official documentation:

procedure SetString(var S: String; Buffer: PChar; Length: Integer);

For a long string variable, SetString sets S to reference a newly allocated string of the given length. If the Buffer parameter is not nil, SetString then copies Len characters from Buffer into the string; otherwise, the content of the new string is left uninitialized. If there is not enough memory available to create the string, an EOutOfMemory exception is raised. Following a call to SetString, S is guaranteed to reference a unique string (a string with a reference count of one).

Some have noticed that in our libraries, I sometimes use SetString instead of SetLength.
When the string is already allocated, it could be faster to use SetString, if you are sure that you will overwrite the string content.

Continue reading

2011-12-11

Strong-typing just rocks

To my understanding, the so-called "strong-typing" feature is one big benefit of the Delphi object pascal language.

As stated by wikipedia:

Most generally, "strong typing" implies that the programming language places severe restrictions on the intermixing that is permitted to occur, preventing the compiling or running of source code which uses data in what is considered to be an invalid way. For instance, an addition operation may not be used with an integer and string values; a procedure which operates upon linked lists may not be used upon numbers. However, the nature and strength of these restrictions is highly variable.

Some Delphi users may find this is a limitation of the language, in comparison with other "fashionable" script idioms (like Python, Javascript of Ruby). For me, runtime strong typing (alla Python or Ruby) is not true strong typing. Simon Stuart just proposed a smartstring kind of string, which is in fact a weakstring type. As far as I understood his point, he wanted to get rid of all the warnings emitted by Unicode-version of the Delphi compiler, about explicit string conversion.

In fact, I use to go in the opposite direction. For wide projects, strong-typing is one of the big benefit of using Delphi (like other main "serious" languages like Java, C, C++, Ada or C#).

Continue reading

2011-12-08

Avoiding Garbage Collector: Delphi and Apple side by side

Among all trolling subject in forums, you'll find out the great Garbage Collection theme.

Fashion languages rely on it. At the core of the .Net and Java framework, and all scripting languages (like JavaScript, Perl, Python or Ruby), you'll find a Garbage Collector. New developers, just released from schools, do learn about handling memory only in theory, and just can't understand how is memory allocated - we all have seen such rookies involved in Delphi code maintenance, leaking memory as much as they type. In fact, most of them did not understood how a computer works. I warned you this will be a trolling subject.

And, in Delphi, there is no such collector. We handle memory in several ways:

  • Creating static variables - e.g. on the stack, inside a class or globally;
  • Creating objects with class instances allocated on heap - in at least three ways: with a try..finally Free block, with a TComponent ownership model in the VCL, or by using an interface (which creates an hidden try..finally Free block);
  • Creating reference-counted variables, i.e. string, array of, interface or variant kind of variables.

It is a bit complex, but it is also deadly powerful. You have several memory allocation models at hand, which can be very handy if you want to tune your performance and let program scale. Just like manual recycling at home will save the planet. Some programmers will tell you that it's a waste of cell brain, typing and time. Linux kernel gurus would not say so, I'm afraid.

Then came the big Apple company, which presented its new ARC model (introduced in Mac OS X 10.7 Lion) as a huge benefit for Objective-C in comparison with the Garbage Collection model. And let's face it: this ARC just sounds like the Delphi memory model.

Continue reading

2011-12-04

Total Commander 64 bit is using... Lazarus and FPC

I'm a long-time registered user of Total Commander.

This tool is my daily file manager. I never use Windows Explorer, since Total Commander is just faster, more easy to use (especially with the keyboard), has a lot of plug-ins. I even created my own plug-ins to access some custom file formats, and navigate into them just like with any folder. And it includes a lot of well written commands for FTP access or file comparison, which made other tools (like WinMerge) unnecessary.

There is a new beta version of Total Commander available, which targets Windows 64 bit. I just thought: 'Whoo, this is a real-world Delphi XE2 64 application'. I downloaded and tried it. Worked as expected, and integrates seamlessly with Windows Seven (for the shell extensions). Then I took a look at the executable... and discovered it was not compiled with Delphi XE2... but with FPC !

Continue reading

2011-11-27

SOLID design principles

Delphi is sometimes assimilated to a RAD product - and this is a marketing label - but IMHO Delphi is much more than RAD.
With Delphi, you can make very serious and clean programming.

Including SOLID style of coding.

The acronym SOLID is derived from the following OOP principles (quoted from the corresponding Wikipedia article):

  • Single responsibility principle: the notion that an object should have only a single responsibility;
  • Open/closed principle: the notion that “software entities ... should be open for extension, but closed for modification”;
  • Liskov substitution principle: the notion that “objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program” - also named as "design by contract";
  • Interface segregation principle: the notion that “many client specific interfaces are better than one general purpose interface.”;
  • Dependency inversion principle: the notion that one should “Depend upon Abstractions. Do not depend upon concretions.”. Dependency injection is one method of following this principle.

If you have some programming skills, those principles are general statements you may already found out by yourself. If you start doing serious object-oriented coding, those principles are best-practice guidelines you would gain following.

They certainly help to fight the three main code weaknesses:

  • Rigidity – Hard to change something because every change affects too many other parts of the system;
  • Fragility – When you make a change, unexpected parts of the system break;
  • Immobility – Hard to reuse in another application because it cannot be disentangled from the current application.

Continue reading

2011-11-23

Does speed matters?

Luigi Sandon wrote on Embarcadero's forum

And then you ask yourself: "why use a native compiler if its code may be even slower than jitted one?". Hope the new developers will also develop better and faster code - and not viceversa.

Embarcadero is just following the Wirth's law slower than others:

"Software is getting slower more rapidly than hardware becomes faster"

Speed is only a matter of compiler for mathematical computing intensive tasks.
Most of the time, in real apps (like business apps), the main speed issue is more the framework size (and the number of dll invoked), memory consumption, and general design (e.g. how caching and SQL are written).

Delphi, Java or .Net can do slow apps.
Delphi, Java or .Net can do fast apps.

You can do small and fast stand-alone apps with Delphi, running from Windows 2000 to Windows 8.
It is not possible with Java nor .Net.

This is the main difference IMHO with native code and JIT - about memory use, ease of distribution and no need of an external runtime framework.

Continue reading

2011-11-08

Currency is your friend

The currency type is the standard Delphi type to be used when storing and handling monetary values. It will avoid any rounding problems, with 4 decimals precision. It is able to safely store numbers in the range -922337203685477.5808 .. 922337203685477.5807. Should be enough for your pocket change.

As stated by the official Delphi documentation:

Currency is a fixed-point data type that minimizes rounding errors in monetary calculations. On the Win32 platform, it is stored as a scaled 64-bit integer with the four least significant digits implicitly representing decimal places. When mixed with other real types in assignments and expressions, Currency values are automatically divided or multiplied by 10000.

In fact, this type matches the corresponding OLE and .Net implementation of currency, and the one used by most database providers (when it comes to money, a dedicated type is worth the cost in a "rich man's world"). It is still implemented the same in the Win64 platform (since XE 2). The Int64 binary representation of the currency type (i.e. value*10000 as accessible via PInt64(aCurrencyValue)^) is a safe and fast implementation pattern.

In our framework, we tried to avoid any unnecessary conversion to float values when dealing with currency values. Some dedicated functions have been implemented for fast and secure access to currency published properties via RTTI, especially when converting values to or from JSON text. Using the Int64 binary representation can be not only faster, but also safer: you will avoid any rounding problem which may be introduced by the conversion to a float type. Rounding issues are a nightmare to track - it sounds safe to have a framework handling natively a currency type from the ground up.

Continue reading

2011-10-27

Yes we can... fight bugs

From a StackOverflow question about a freezing Delphi application, I posted some experiment-based debugging tricks.

May help any developer in his/her fight against random bugs...

Continue reading

2011-09-25

Some thoughts about OSX integration in XE2

You know all that one of the most exciting features of Delphi XE2 is the MaxOSX Cross-Platform feature.
You've got the UI part, that is FireMonkey, but underneath, you did have some RTL modifications in order to let our Windows-centric solutions be OSX ready.

The first main step was to make our code speak with the "Objective-C" way of coding.

Objective-C is the primary language used for Apple's Cocoa API, and it was originally the main language on NeXT's NeXTSTEP OS. It's some object-oriented C variant, but something other than C++ or Java. In fact, Objective-C sounds more like a SmallTalk variance of C than another  C++/Java/C# flavor. For instance, the Objective-C model of object-oriented programming is based on message passing to object instances: this is just another way of doing it. It has some advantages, and disadvantages (I don't want to troll here) - but it is definitively nice. And the memory model is just something else, more close to our reference-counting way (as in Delphi interface implementation) than a garbage collector.

Continue reading

2011-09-12

Using Extended in Delphi XE2 64 bit

Unfortunately, Delphi's 64-bit compiler (dcc64) and RTL do not support 80-bit extended floating point values on Win64, but silently alias Extended = Double on Win64.

There are situations, however, where this is clearly undesirable, e.g. if the additional precision gained from Extended is required.

The Open-source uTExtendedX87 unit provides a replacement FPU-backed 80-bit Extended floating point type (TExtendedX87) for Win64.

Continue reading

2011-08-28

Multi-threading and Delphi

Writing working multi-threaded code is not easy - it's even hard, as as a Delphi expert just wrote in his blog.

In fact, the first step into multi-thread application development could be:

"protect your shared variables with locks (aka critical sections), because you are not sure that the data you read/write is the same for all threads".

The CPU per-core cache is just one of the possible issues, which will lead into reading wrong values. Another issue which may lead into race condition is two threads writing to a resource at the same time: it's impossible to know which value will be stored afterward.

Continue reading

2011-08-11

FireMonkey and DXScene

For those how are interested in FireMonkey, I made some screenshots of some DXScene sample app.

It may give you some good starting point about the features of the upcoming Delphi XE2 user interface components.

Continue reading

2011-06-16

Which Delphi compiler produces faster code?

After a question on StackOverflow, I wanted to comment about the speed of generated code by diverse Delphi compiler versions.

Since performance matters when we write general purpose libraries like ours, we have some feedback to propose:

Continue reading

2011-06-07

Intercepting exceptions: a patch to rule them all

In order to let our TSynLog logging class intercept all exceptions, we use the low-level global RtlUnwindProc pointer, defined in System.pas.

Alas, under Delphi 5, this global RtlUnwindProc variable is not existing. The code calls directly the RtlUnWind Windows API function, with no hope of custom interception.

Two solutions could be envisaged:

  • Modify the Sytem.pas source code, adding the new RtlUnwindProc variable, just like Delphi 7; 
  • Patch the assembler code, directly in the process memory.

The first solution is simple. Even if compiling System.pas is a bit more difficult than compiling other units, we already made that for our Enhanced RTL units. But you'll have to change the whole build chain in order to use your custom System.dcu instead of the default one. And some third-party units (only available in .dcu form) may not like the fast that the System.pas interface changed...

So we used the second solution: change the assembler code in the running process memory, to let call our RtlUnwindProc variable instead of the Windows API.

Continue reading

True per-class variable

For our ORM, we needed a class variable to be available for each TSQLRecord class type.

This variable is used to store the properties of this class type, i.e. the database Table properties (e.g. table and column names and types) associated with a particular TSQLRecord class, from which all our ORM objects inherit.

The class var statement was not enough for us:
- It's not available on earlier Delphi versions, and we try to have our framework work with Delphi 6-7 up to XE;
- This class var instance will be shared by all classes inheriting from the class where it is defined - and we need ONE instance PER class type, not ONE instance for ALL

We needed to find another way to implement this class variable

An unused VMT slot in the class type description was identified, then each class definition was patched in the process memory to contain our class variable.

Continue reading

2011-05-26

Calling a 64 bit library from a Delphi 32 bit process

Since we are still waiting for a Delphi 64 bit compiler, the only available solution to access a 64 bit library from an application written in Object pascal, is to use the 64 bit version of the FreePascal Compiler.

But you just can not recompile your VCL/GUI based Delphi application with FPC:

  • Some low-level part of your code may not be directly compatible with a 64 bit process (e.g. since the pointer size changed);
  • The GUI part of the application can not be ported directly with FPC - the Lazarus project try to be as close as possible to VCL, but it can be a very difficult, either impossible if you use some third-party components.
I just found out a solution from CodeCentral, allowing to call any 64 bit dll from a Delphi 32 bit process.

Continue reading

- page 3 of 4 -