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

Indy10, TIdSMTP, how to get protocol log?

Posted by jpluimers on 2020/12/17

Indy is great, but not well documented so: [WayBack] Indy10, TIdSMTP, how to get protocol log? I try to get log from SMTP communication, like this (copy from wiki): {code} S: 220 smtp.example.com ESMTP P… – Jacek Laskowski – Google+

Q

Indy10, TIdSMTP, how to get protocol log?

I try to get log from SMTP communication, like this (copy from wiki):

{code}
S: 220 smtp.example.com ESMTP Postfix
C: HELO relay.example.com
S: 250 smtp.example.com, I am glad to meet you
C: MAIL FROM:<bob@example.com>
S: 250 Ok
C: RCPT TO:<alice@example.com>
S: 250 Ok
C: RCPT TO:<theboss@example.com>
S: 250 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: "Bob Example" <bob@example.com>
C: To: Alice Example <alice@example.com>
C: Cc: theboss@example.com
C: Date: Tue, 15 January 2008 16:02:43 -0500
C: Subject: Test message
{code}

but without success :-(

I try use many events from TIdSMTP, TIdLogEvent, TIdSSLIOHandlerSocketOpenSSL but result is low level like bytes, status etc. not true SMTP log.

How to do it?

A

Sending stuff still might be tough, so you might want to consider alternatives too: [WayBack] I need to add to the REST server the ability to send emails with attachments of different types. Which library is best to use? Indy or maybe ICS? Of cou… – Jacek Laskowski – Google+

Q

I need to add to the REST server the ability to send emails with attachments of different types. Which library is best to use? Indy or maybe ICS? Of course with SSL/TLS support.

A

Dany Marmur's profile photo

+Balázs Szakály, YES! Synapse. Let’s get people using it more. You can give it some criticism surely, but consider the pro’s:

It is straight-forwardly-written so when you hit a wall you can read the code easily (compared to other solutions),

You can inherit, extend and extrapolate, re-use and tweak,

Very Delphi-ish (TMimeMessages = TStringList or some such, not at at devmachine atm)

Compact and free!

Quite stable too.

–jeroen

Posted in Communications Development, Delphi, Development, Indy, Internet protocol suite, SMTP, Software Development | Leave a Comment »

Spinettaro’s Blog: Delphi Flux application architecture

Posted by jpluimers on 2020/12/16

On my list of things to try: [WayBack] Spinettaro’s Blog: Delphi Flux application architecture.

It is about a Delphi implementation of the Facebook Flux application architecture.

Related:

Via: [WayBack] Delphi Flux application architecture A good application architecture Finding a good application architecture is not easy, but defining an architecture f… – Daniele Spinetti – Google+

Note that by using the [WayBack] CodeRage 2018 Replay | Embarcadero Academy, you are disallowed using any of what you learn in a commercial way.

Embarcadero evangelists told the public that for the Community Edition, similar terms would not be upheld, but then the sales department started sending out nasty emails to people registering Community Edition using their work email address.

[WayBackhttps://www.embarcaderoacademy.com/p/terms:

under this license you may not:

  1. modify or copy the materials;
  2. use the materials for any commercial purpose, or for any public display (commercial or non-commercial);
  3. attempt to decompile or reverse engineer any software contained on the School’s web site;
  4. remove any copyright or other proprietary notations from the materials; or
  5. transfer the materials to another person or ‘mirror’ the materials on any other server.

–jeroen

Read the rest of this entry »

Posted in Delphi, Development, JavaScript/ECMAScript, Scripting, Software Development, Systems Architecture, TypeScript | Leave a Comment »

System.SyncObjs.TLightweightSemaphore.Create: the AInitialCount parameter

Posted by jpluimers on 2020/12/16

Multi-threading is hard, knowing your primitives is important, but Embarcadero documentation is always far from complete, leading to [WayBack] System.SyncObjs.TLightweightSemaphore.Create: Please simply explain to me the parameters of this constructor, especially first, AInitialCount… – Jacek Laskowski – Google+

The concept of semaphores is universal (the free book [WayBack] The Little Book of Semaphores – Green Tea Press is great), but the implementation/wrapping can slightly differ, so on the [Archive.is] XE introduced TLightweightSemaphore.Create parameters:

  • Primož Gabrijelčič's profile photo

    Semaphore is used to allow ‘counted’ access. It allows access to as much owners as it has maximum count. If you wait on a semaphore (WaitFor) and wait succeeds, the semaphore’s count is decremented. When it drops to 0, no new Wait will succeed.

    When you call Release, the semaphore’s count is incremented which allows somebody else to own the semaphore.

    Parameters simply set the initial state for this count and maximum value of the counter. Usually you’ll both set to the same value.

  • Primož Gabrijelčič's profile photo

    If you intend to use semaphores, read this. Great book.

    The Little Book of Semaphores – Green Tea Press
    greenteapress.com
  • Jacek Laskowski's profile photo
    I know (theoretically) how a semaphore works. I even used this semaphore class in production code.
    I want to create as many threads as there are cores in the processor (+ 1 additional, little loaded).fCoreController := TLightweightSemaphore.Create(TThread.ProcessorCount, TThread.ProcessorCount + 1);But now it turned out that customers who have CPUs with one core (yes, there are those), this code blocks the remaining threads. And I am looking for a reason, maybe I misunderstand this semaphore. What does AInitialCount mean?

    ps. Delphi Seattle

  • Stefan Glienke's profile photo
    AInitialCount is the number of entires a semaphore has left when created. If that is one less than AMaxCount that means you already gave one entry away. I just do a wild guess and say that you might do a Wait on the created semaphore shortly after creating it and in some other thread as well but since for one CPU your AInitialCount is only 1, one of them will block – possibly you created a deadlock situation here.
  • Jacek Laskowski's profile photo
    +Stefan Glienke Ok, if I want threads to be given a semaphore so that they work when it’s open (thread execute -> Semaphor.WaitFor) and I want to have as many threads as there are cores (+1 additional) then how should I create TLightweightSemaphore object?
  • Stefan Glienke's profile photo
    What Primoz said at the end of the very first comment – put same value for both: TThread.ProcessorCount + 1
  • Jacek Laskowski's profile photo

 

–jeroen

 

Posted in Delphi, Development, Multi-Threading / Concurrency, Software Development | Leave a Comment »

In Delphi, avoid having a TComponent descendant implement interfaces, unless you are prepared to handle your refcounting

Posted by jpluimers on 2020/12/15

Every now and then I see code, where a class descending from TComponent implements some interfaces, only interface references are used to the instances, and the expected behaviour is that the instances will free themselves when all the references went out of scope.

Bummer: TComponent by default is not reference counted.

It is when you assign VCLComObject an IVCLComObject which is hell to implement (Delphi provides two of them: TVCLAutoObject and TActiveFormControl. They sound heavey, and are).

Do not go that way. If you need some form of ownership in a class implementing an interface, then descend the class from TInterfacedObject, and add a field of TComponent that is the owner of things that need to be freed later on. In the destructor, free that field.

Something like this:

unit InterfacedObjectWithRootUnit;

interface

type
   TInterfacedObjectWithRoot = class(TInterfacedObject)
   strict private
      FRoot: TComponent;
      function GetRoot: TComponent;
   strict protected
      property Root: TComponent read GetRoot;
   public
      destructor Destroy; override;
   end;

implementation

destructor TInterfacedObjectWithRoot.Destroy;
begin
  if Assigned(FRoot) then
  begin
    FRoot.Free();
    FRoot := nil;
  end;
  inherited Destroy();
end;

function TInterfacedObjectWithRoot.GetRoot: TComponent;
begin
  if FRoot = nil then
    FRoot := TComponent.Create(nil);
  Result := FRoot;
end;

end.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Delphi TRegExOption: Where is description of roNotEmpty option? What does this option do? – Jacek Laskowski – Google+

Posted by jpluimers on 2020/12/10

I really dislike using regular expressions, mainly because every time I bump into code using them either:

  • I cannot decipher them any more
  • It is used for things not suites for (like parsing JSON or XML: please don’t!)

For more background on when NOT to use regular expressions, remember they describe a regular grammar, and can only me implemented by a finite state machine (a state machine that can be exactly one state out of a set of finite states).

As soon as you need to parse something that needs multiple states at once, or the number of states becomes infinite,

Some background reading:

Read the rest of this entry »

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

How To Write Unmaintainable Code: Ensure a job for life ;-) by Roedy Green Canadian Mind Products

Posted by jpluimers on 2020/12/09

A great reference on how not to code still is

How To Write Unmaintainable Code

Ensure a job for life ;-)

Roedy Green Canadian Mind Products

I am still amazed when browsing through code, how many people use one or more of the anti-patterns in it.

One example I came across was this piece of Delphi RTL code:

class function TMarshalUnmarshalBase.ComposeKey(clazz: TClass; Field: string): string;
begin
  if clazz <> nil then
    Result := clazz.UnitName + SEP_DOT + clazz.ClassName + SEP_DOT + Field
  else
    Result := '';
end;

So I did a quick search at in the Delphi RTL for clazz, then found these occurences, indicating not only the authors of them have been under a rock, but also the code reviewers:

  • 98 in data\dbx\Data.DBXJSONReflect.pas
  • 7 in data\dbx\Data.DBXTransport.pas
  • 97 in data\rest\REST.JsonReflect.pas
  • 3 in DUnit\src\TestFramework.pas
  • 22 in indy\abstraction\IPPeerAPI.pas

I have seen similar things in many environments, even run-time libraries of others, though this is one of the worst examples and falls under the anti-pattern:

Thesaurus Surrogatisation

To break the boredom, use a thesaurus to look up as much alternate vocabulary as possible to refer to the same action, e.g. displayshowpresent. Vaguely hint there is some subtle difference, where none exists. However, if there are two similar functions that have a crucial difference, always use the same word in describing both functions (e.g. print to mean “write to a file”, “put ink on paper” and “display on the screen”). Under no circumstances, succumb to demands to write a glossary with the special purpose project vocabulary unambiguously defined. Doing so would be an unprofessional breach of the structured design principle of information hiding.

There is a great other anti-pattern in the document too:

Delphi/Pascal Only

: Don’t use functions and procedures. Use the label/goto statements then jump around a lot inside your code using this. It’ll drive ’em mad trying to trace through this. Another idea, is just to use this for the hang of it and scramble your code up jumping to and fro in some haphazard fashion.

Enjoy reading the anti-pattern descriptions, which are now maintained at [WayBack] GitHub – Droogans/unmaintainable-code: A more maintainable, easier to share version of the infamous http://mindprod.com/jgloss/unmain.html, as it was originally a multi-page hard to maintain set of small articles:

A lot of comments were posted because of it: [WayBack] Responses to Roedy’s Unmaintainable Code Essay

Via:

–jeroen

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

Delphi and SuperObject JSON support have a very different implementation

Posted by jpluimers on 2020/12/09

In the comments of [WayBack] Delphi and JSON Is there an overlay (eg in the form of a helper) for the JSON classes built into Delphi (System.JSON), which offered an interface simil… – Jacek Laskowski – Google+

SuperObject has a very different implementation for JSON support than the Delphi RTL System.JSON unit as explained by Dalija Prasnikar:

If you are thinking about replacing existing code that uses SuperObject with Delphi build in JSON library, you have another problem on desktop – non-ARC compiler. SuperObject classes are interface based (reference counted) and Delphi JSON is class based – non ref-counted.

These methods are not in the Delphi RTL because of the difference:

How to read a property value of an object ?

  val := obj.AsObject.S['foo']; // get a string
  val := obj.AsObject.I['foo']; // get an Int64
  val := obj.AsObject.B['foo']; // get a Boolean
  val := obj.AsObject.D['foo']; // get a Double
  val := obj.AsObject.O['foo']; // get an Object (default)
  val := obj.AsObject.M['foo']; // get a Method
  val := obj.AsObject.N['foo']; // get a null object

How to read a value from an array ?

  // the advanced way
  val := obj.AsArray.S[0]; // get a string
  val := obj.AsArray.I[0]; // get an Int64
  val := obj.AsArray.B[0]; // get a Boolean
  val := obj.AsArray.D[0]; // get a Double
  val := obj.AsArray.O[0]; // get an Object (default)
  val := obj.AsArray.M[0]; // get a Method
  val := obj.AsArray.N[0]; // get a null object

–jeroen

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

delphi “tproc” with “array of const” – Google Search

Posted by jpluimers on 2020/12/08

Reminder to self: remember which of the open source libraries have:

  • a generic TProc<T> alike with an const values: array of const T parameter
  • a generic TProc<T> alike with a const value: T parameter

Google returned none that stuck:

The Delphi RTL does not contain them, and because they forgot setting them up with const parameters, these can never be changed:

[WayBack] System.SysUtils.TProc – RAD Studio API Documentation

TProc = reference to procedure;
TProc<T> = reference to procedure (Arg1: T);
TProc<T1,T2> = reference to procedure (Arg1: T1; Arg2: T2);
TProc<T1,T2,T3> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3);
TProc<T1,T2,T3,T4> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4);

More people are annoyed by this, for instance [WayBack] SysUtils.pas Why parameters of these anonymous not const? TProc = reference to procedure (Arg1: T1; Arg2: T2); TProc = reference … – Jacek Laskowski – Google+

SysUtils.pas

Why parameters of these anonymous not const?

TProc<T1,T2> = reference to procedure (Arg1: T1; Arg2: T2);
TProc<T1,T2,T3> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3);
TFunc<T,TResult> = reference to function (Arg1: T): TResult;
TFunc<T1,T2,TResult> = reference to function (Arg1: T1; Arg2: T2): TResult;

  • David Heffernan's profile photo
    Because the designer made a bloody terrible mistake 
  • Asbjørn Heid's profile photo
    To be fair, const-ness is a bloody mess in Delphi…
  • Hallvard Vassbotn's profile photo
    It could have been solved if the const’ness had been seen as a implementation detail by the compiler (which it really is) and made const and non-const signatures assignment compatible.
  • David Heffernan's profile photo
    +Hallvard Vassbotn indeed, and it pains me that this has never happened
  • Hallvard Vassbotn's profile photo
    +Marco Cantu Any chance of a compiler improvement in the future with regards to relaxing const matching in signature assignments…? :)
  • Vincent Parrett's profile photo
    I’ve taken to defining
    TConstProc<T1,T2> = reference to procedure (const Arg1: T1; const Arg2: T2);for cases where I have full control.

  • David Heffernan's profile photo
    +Vincent Parrett I’m sure we all have our own versions of this. But it’s not much use for composition of course.
  • Vincent Parrett's profile photo
    +David Heffernan Yup. Since it’s unlikely the compiler will every be updated to make const an automatic thing, perhaps they could add const versions to the RTL.
  • Allen Drennan's profile photo
    Yeah, we end up making our own versions of these to add the consts in all our projects.
  • David Millington's profile photo
    Do file a QP, please. Major releases like the upcoming 10.3 are the time to make interface-breaking changes.

–jeroen

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

.NET: interfaces that inherit from multiple base interfaces

Posted by jpluimers on 2020/12/03

For my link archive:

Read the rest of this entry »

Posted in .NET, C#, Delphi, Development, Software Development | Leave a Comment »

I’m using Delphi XE 10.2: empty documentation tab means you need to update to either the documentation Hotfix or 10.2.3

Posted by jpluimers on 2020/12/03

If you see the Documentation tab like below you need to either:

The problem is caused by Embarcadero using mixed technologies in the Delphi IDE combined with their lack of testing due to not eating their own dog-food.

Too bad, as the documentation over the last versions has finally increased after a 10+ year steady decline.

Doing one technology right is hard, but having to mix multiple technologies into one product is extremely hard.

Via: [WayBack] I’m using Delphi XE 10.2. Whenever I click on the Documentation tab, I see the following uselessly rendered page. I can’t seem to resize it either. Anyb… – Graeme Geldenhuys – Google+

–jeroen

Read the rest of this entry »

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