The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,862 other subscribers

Archive for the ‘Delphi’ Category

Canonical Delphi Singleton Pattern – Stack Overflow

Posted by jpluimers on 2017/11/29

Though I try to refrain from using the singleton pattern when possible (I prefer dependency injection over accessing “globals” that usually tend up to be not so global after all), sometimes I need to.

In C# there has been a canonical singleton pattern implementation by John Skeet for a very long time at [WayBackC# in Depth: Implementing the Singleton Pattern.

I just found out there has been similar implementations in Delphi both in this question (which like many useful questions is marked “closed”, oh the joy of StackOverflow): [WayBack] “Delphi Singleton Pattern – Stack Overflow:

I like both implmentation, but usually take the first as mostly locking has little overhead and sometimes two instances cannot co-exist (though that’s lessened when part of the singleton uses lazy initialisation, for instance from Spring4D).

–jeroen

via: [WayBack] May I please ask for your opinion on the following code:..singleton… – John Kouraklis – Google+

Posted in Delphi, Development, Software Development | Leave a Comment »

tiOPF discussion thread

Posted by jpluimers on 2017/11/29

Sometimes the title of a G+ entry looks not so interesting, but then you read the comments. In this cast it’s about the mediator pattern support in the tiOPF object persistence framework, how it works very well from Free Pascal and both classic and  modern Delphi compilers and why developers dislike ARC. It’s cool as it allows you to decouple UI from business logic and separate out business logic from your application into a back-end. Recommended reading: [WayBack] Hello i have a program that use MS SQL SERVER 2000i want to make a mobile application that connect to this database to make some consultationclient fi… – Mohammed Bouhlal – Google+

–jeroen

Posted in Delphi, Development, FreePascal, Pascal, Software Development | Leave a Comment »

Implementing Memoize in Delphi 2009 – Community Blogs – Embarcadero Community

Posted by jpluimers on 2017/11/28

I think it was Stefan Glienke who pointed me at the Memoisation pattern: [WayBackImplementing Memoize in Delphi 2009 – Community Blogs – Embarcadero Community

Or in laymans terms: caching with generic functions and dictionaries.

Note the Archive.is link is way better readable than the WayBack link, so below I’ve saved parts only in Archive.is.

It points to two other interesting reads:

Later I found it was indeed Stefan who pointed me to the above links and also came up with this very small Memoisation example which is based on Spring4D:

and guess what? because we have interfaced based dictionary this is super easy, let me just hack an example, 5mins6:52 PM

function BuildCache: Tfunc<string,string>;
var
 cache: IDictionary<string,string>;
begin
 cache := TCollections.CreateDictionary<string,string>;
 Result :=
   function(s: string): string
   begin
     if not cache.TryGetValue(s, Result) then
     begin
       Sleep(1000); // hard work! ;)
       Result := ReverseString(s);
       cache.Add(s, Result);
     end;
   end;
end;

Since the returned anonymous method captures the dictionary its kept inside and once the anonymous method goes out of scope the dictionary is also cleaned, want to reset the cache? Just create a new one and throw the old one away.

Need thread safety? just add

System.TMonitoy.Enter/Leave(cache.AsObject);

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Use operator overloading for classes with non-ARC compiler · GitHub

Posted by jpluimers on 2017/11/23

[WayBackUse operator overloading for classes with non-ARC compiler · GitHub

The trick: do not use class operator but use class function &&op_ with the special operator name in the table referenced below. Just follow the bulleted example links to get an idea.

Bonus: it works on class helper constructs as well.

Officially this unsupported and with the non-ARC compiler you will have a risk of memory leaks.

But it’s so much fun as these links prove:

The usual operator gotchas apply here as well: Delphi operator overloading: table of operators, names, and some notes on usage and ‘glitches’.

The operators you could try: [WayBackOperator Overloading (Delphi) – RAD Studio

Oh, this thread needs some change now: [WayBackList of Delphi language features and version in which they were introduced/deprecated – Stack Overflow

–jeroen

Posted in Delphi, Development, Software Development | 1 Comment »

Capitalization Conventions – more than Canceled not Cancelled

Posted by jpluimers on 2017/11/23

[WayBackCapitalization Conventions

Posted in .NET, Delphi, Development, Software Development | 1 Comment »

check if network connection is permanent

Posted by jpluimers on 2017/11/22

Thanks Uwe for the below code!

I was in a situation of a batch file running from a Task Scheduler that got broken because the user suddenly turned on persistent network connections.

So I needed to check if a shared drive-letter was indeed persistent or not and act accordingly.

The below code helped me merging the batch file with the Delphi application it would run in the background anyway.

It’s way better than checking of the global “persistence” flag for new connections has been set in the registry: [WayBackSaveConnections flag at HKCU\Software\Microsoft\Windows NT\CurrentVersion\Network\Persistent Connections (which is reflected both in the Windows UI and settable via net use /Persistent).

Source: check if network connection is permanent

Via: [WayBack] Anyone who can share how one can query if a drive letter mapping to a share is persistent across logon sessions? (yes, this is Windows, I know) – Jeroen Wiert Pluimers – Google+

–jeroen

Read the rest of this entry »

Posted in Delphi, Development, Software Development | Leave a Comment »

Delphi history: No, dynamic arrays do not support a non-zero lower bound, but what if you want them? – via Stack Overflow

Posted by jpluimers on 2017/11/21

A post of some older Delphi stuff I did in the past just in case need it again.

David Heffernan found the documentation for this: [WayBackStructured Types (Delphi): Dynamic Arrays – RAD Studio

Since I needed a dynamic array structure supporting a non-zero lower bound, I was glad he also provided an answer with a data structure that does provide a non-zero lower bound.

For my own reference I’ve put his answers and questions below (as it’s way easier to search my blog than the complete internet) and my own implementation:

Read the rest of this entry »

Posted in Delphi, Development, History, Software Development | 10 Comments »

Hi! how to hide a property in object inspector? i have my custom components …

Posted by jpluimers on 2017/11/16

For my link archive:

Some quotes

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

FastMM4 + Delphi – Recompiling application with 10.2.1 causes memory leaks?

Posted by jpluimers on 2017/11/15

This is why you should always test your Delphi apps with FastMM4 and FullDebugMode enabled: [WayBack] Delphi – Recompiling application with 10.2.1 causes memory leaks?

A workaround is to add the below code in either of these places:

  • end of your .dpr file right before the end.
  • in the finalization section of a new unit

CheckSynchronize();

It calls the [WayBackSystem.Classes.CheckSynchronize method to ensure the background thread performs the needed cleanup.

Thanks Stefan Glienke for solving this.

–jeroen

Read the rest of this entry »

Posted in Delphi, Delphi 10.2 Tokyo (Godzilla), Development, Software Development | Leave a Comment »

Delphi: ^TNodeData incompatible with PNodeData – {$T+} versus {$T-}

Posted by jpluimers on 2017/11/14

In my Turbo Pascal days, I was fan of the {$T+} directive (now a.k.a TypedAddress on) as it would make the @ operator return typed pointers and the compiler would be more strict in forcing checks on pointer types to be compatible.

Not so much in Delphi any more, see the below comment on in a G+ thread on Delphi pointer type compatibility [WayBack] by David Millington from Embarcadero.

Basically we’re stuck with {$T-} which is a double edged sword:

  • on the one hand it forces you to ensure your typed pointers are always the same actual type (so you need to define a type like PNodeData once and use it everywhere)
  • on the other hand it still allows the generic Pointer type to be compatible with typed pointers which means people use that and will not have the benefit of typed pointer checking

David Millington:

So the question is why is PNodeData different to ^TNodeData? These two pages have the answer:

  • “Two distinct types are compatible if they satisfy at least one of the following conditions:
    … (snip)
  • One type is Pointer (an untyped pointer) and the other is any pointer type.
  • Both types are (typed) pointers to the same type and the {$T+} compiler directive is in effect.”

[WayBackhttp://docwiki.embarcadero.com/RADStudio/Berlin/en/Type_Compatibility_and_Identity_(Delphi)#Type_Compatibility

That line about $T+ is key; it’s the “Typed @ operator” compiler option which is off by default. “In the {$T-} state, distinct pointer types other than Pointer are incompatible (even if they are pointers to the same type)”. So with that off, PNodeData and ^TNodeData are different.

[WayBackhttp://docwiki.embarcadero.com/RADStudio/en/Type-checked_pointers_(Delphi)

The best solution is to define PNodeData, as you’ve done, and use it everywhere.

What David fails to mention there, and I added as a commen later is this:

The problem $T is that it’s a two-edged sword as it makes code that looks valid fail to compile because the compiler in the $T+ state (a.k.a. $TypedAddress on state) never got updated to:

  • handle @ to an array creates a pointer to the element of that array
  • handle @ to resourcestrings to become PResStringRec (and likely more examples)

Which means the below programs fail to compile.

The alternative (adding way more {$T+} compatible overloads to the RTL/VCL/FMX) was never done either, so now we’re stuck with {$T-}

Array of char example:

program TypedAddressDirectiveWithCharArrays;

{$APPTYPE CONSOLE}

{$TypedAddress on}

uses
  Winapi.Windows;

var
  TimeZone: string;
  TZ: TTimeZoneInformation;

begin
  TimeZone := 'Coordinated Universal Time';
  StringToWideChar(TimeZone, @(TZ.StandardName), SizeOf(TZ.StandardName) div SizeOf(WideChar));
end.

(*

[dcc32 Error] TypedAddressDirectiveWithCharArrays.dpr(16): E2010 Incompatible types: 'PWideChar' and 'Pointer'

In the System unit:

implicit types:

  PWideChar = WideChar;
  PChar = PWideChar

explicit:

function StringToWideChar(const Source: UnicodeString; Dest: PWideChar; DestSize: Integer): PWideChar;



In the Winapi.Windows unit:

type
  WCHAR = WideChar;

  PTimeZoneInformation = ^TTimeZoneInformation;
  _TIME_ZONE_INFORMATION = record
    Bias: Longint;
    StandardName: array[0..31] of WCHAR;
    StandardDate: TSystemTime;
    StandardBias: Longint;
    DaylightName: array[0..31] of WCHAR;
    DaylightDate: TSystemTime;
    DaylightBias: Longint;
  end;
  TTimeZoneInformation = _TIME_ZONE_INFORMATION;
  TIME_ZONE_INFORMATION = _TIME_ZONE_INFORMATION;

*)

ResourceString example:

program TypedAddressDirectiveWithResourceStrings;

{$APPTYPE CONSOLE}

{$TypedAddress on}

uses
  System.SysConst,
  System.SysUtils;

procedure RangeError;
begin
  raise ERangeError.CreateRes(@SRangeError);
end;

begin
end.

(*
[dcc32 Error] TypedAddressDirectiveWithResourceStrings.dpr(13): E2250 There is no overloaded version of 'CreateRes' that can be called with these arguments


System unit:

type
  PResStringRec = ^TResStringRec;
  {$IF defined(EXTERNALLINKER)}
  TResStringRec = record
    Key: MarshaledAString;
  end;
  {$ELSE}
  TResStringRec = packed record
    // 32bit = 8 bytes
    // 64bit = 16 bytes
    Module: ^HMODULE;
    Identifier: NativeUint;
  end;
  {$ENDIF}


System.SysConst unit:

resourcestring
  SRangeError = 'Range check error';


SysUtils unit:

constructor Exception.CreateRes(ResStringRec: PResStringRec);
begin
  FMessage := LoadResString(ResStringRec);
end;


*)

Source: [WayBackOn Friday I had a brain fade moment (which I don’t seems to have recovered…

–jeroen

Posted in Delphi, Development, Software Development | 2 Comments »