Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The initialization part is not called

I'm maintaining the VirtualTreeView component for Delphi and C++Builder. With Delphi everything is okay but when I compile the packages with the C++Builder the code in the initialization part in the Delphi units is not called. Any ideas?

like image 620
Roman Kassebaum Avatar asked Nov 16 '15 14:11

Roman Kassebaum


1 Answers

When a Delphi unit's initialization/finalization sections are not being called in a C++Builder project, it usually means the Delphi unit is not being linked into the final executable, typically because the C++ code is not directly referencing any code in the unit, so it gets optimized out. C++Builder is a bit more aggressive about removing unused code than Delphi is. In Delphi, simply adding a unit to a uses clause forces that unit to be linked to. That is not the case in C++. #includeing a Delphi unit's .hpp file in C++ code is not enough to guarantee the unit is linked to, if the C++ code does not use anything from the .hpp file.

Indy ran into this problem in several of its units, most notably IdAllAuthentications, IdAllFTPListParsers, and IdAllHeaderCoders. These units all contain only initialization/finalization code, no interface code, so their generated .hpp files were basically empty. To force linkage, I had to add {$HPPEMIT} statements to the interface section to output #pragma link statements in the generated .hpp files. For example:

unit IdAllAuthentications;

interface

{
Note that this unit is simply for listing ALL Authentications in Indy.
The user could then add this unit to a uses clause in their program and
have all Authentications linked into their program.

ABSOLUTELY NO CODE is permitted in this unit.

}

{$I IdCompilerDefines.inc}

// RLebeau 2/14/09: this forces C++Builder to link to this unit so
// the units can register themselves correctly at program startup...

{$IFDEF HAS_DIRECTIVE_HPPEMIT_LINKUNIT}
  {$HPPEMIT LINKUNIT}
{$ELSE}
  {$HPPEMIT '#pragma link "IdAllAuthentications"'}
{$ENDIF}

implementation

// uses units that self-register in their initialization sections ...

end.

{$HPPEMIT LINKUNIT} was introduced in XE5 Update 2, to help with linking units that use unit-scope names:

New: You can now use HPPEMIT Delphi compiler directives for linking and generating C++ namespace declarations.

...

{$HPPEMIT LINKUNIT} replaces #pragma link for the iOS device target platform. For more information, see HPPEMIT.

For C++ applications, {$HPPEMIT LINKUNIT} replaces #pragma link on mobile platforms.

The Delphi run time has units that must be linked in order to enable some functionality. In C++, auto-linking was previously achieved using the following directive:

{$HPPEMIT '#pragma link "<unitname>"'}

Now you should use the following directive instead:

{$HPPEMIT LINKUNIT}

LINKUNIT generates a #pragma link statement that references the calling unit using the correct decorated/namespaced unit name.

like image 177
Remy Lebeau Avatar answered Nov 12 '22 19:11

Remy Lebeau