The initialization part is not called
Asked Answered
A

1

6

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?

Aryanize answered 16/11, 2015 at 14:49 Comment(11)
I for one cannot understand the question. It's lacking in detail. Could you show maybe some small repro code to demonstrate your point.Bornholm
Are you expecting Delphi code to be compiled/executed when building under C++ Builder? Those are two different languages...Rossiter
@Jerry: I can't speak for Roman, but I certainly expect Delphi code to be compiled and executed when used in C++Builder. What do you think the VCL is? And it is a bit disconcerting that init or finit code is not called from C++Builder.Zaccaria
@RudyVelthuis I could be wrong, as I've never used C++ Builder, but I would expect a C++ project to be all C++ code. It's my understanding the VCL is replicated in C++ code, never imagined C++ and Delphi combined in the same compilation.Rossiter
@Jerry, C++ Builder can consume Delphi-compiled DCUs and BPLs. The VCL is not replicated in multiple languages.Hatchway
@Jerry:C++ Builder uses Delphi code for all of the VCL components. It contains its own Delphi compiler. Every VCL component on the Delphi palette is also available to C++ Builder. So yes, C++ Builder executes Delphi code.Udometer
Yes, you obviously never used C++Builder. It uses the Delphi VCL or FMX and parts of the VCL and other Delphi code. Uncompiled code is compiled by the Delphi compiler into object files (and headers), and these are linked together with the C++ units, in C++Builder. So yes, they are compiled and executed and used by C++.Zaccaria
@Jerry: what is "replicated" is merely the interface section of a Delphi unit. It is compiled (by the Delphi compiler) into a C++ header.Zaccaria
C++ Builder does not execute Delphi code. It compiles Delphi code and then links it.Bornholm
The resulting program does execute Delphi code, though.Zaccaria
@RomanKassebaum Possibly of interest to you: #60115496Ursel
H
10

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.

Homoeo answered 16/11, 2015 at 16:17 Comment(2)
I added to the VirtualTreesCR.cpp file the following line: #pragma link "VirtualTrees" And to the VirtualTrees.pas {$HPPEMIT '#pragma link "VirtualTrees"'} But the designtime package itself already has the problem. I simply drop the VirtualTree on a form and I get an AV because some variables are not assigned.Aryanize
@Remy: We can set breakpoints in the methods and constructors of those units, so I guess the unit was linked in. Interestingly we cannot set a breakpoint in the code of the initialization section of the VirtualTrees unit. So either this is not supported in C++ Builder, or the initialization section of the unit was not linked, but the rest of the unit was.Stocktonontees

© 2022 - 2024 — McMap. All rights reserved.