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?
-
1I for one cannot understand the question. It's lacking in detail. Could you show maybe some small repro code to demonstrate your point. – David Heffernan Nov 16 '15 at 14:56
-
Are you expecting Delphi code to be compiled/executed when building under C++ Builder? Those are two different languages... – Jerry Dodge Nov 16 '15 at 15:20
-
@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. – Rudy Velthuis Nov 16 '15 at 15:54
-
@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. – Jerry Dodge Nov 16 '15 at 15:56
-
2@Jerry, C++ Builder can consume Delphi-compiled DCUs and BPLs. The VCL is not replicated in multiple languages. – Rob Kennedy Nov 16 '15 at 15:59
-
@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. – Ken White Nov 16 '15 at 16:00
-
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++. – Rudy Velthuis Nov 16 '15 at 16:00
-
1@Jerry: what is "replicated" is merely the interface section of a Delphi unit. It is compiled (by the **Delphi** compiler) into a C++ header. – Rudy Velthuis Nov 16 '15 at 16:02
-
C++ Builder does not execute Delphi code. It compiles Delphi code and then links it. – David Heffernan Nov 16 '15 at 17:03
-
The resulting program does execute Delphi code, though. – Rudy Velthuis Nov 17 '15 at 07:17
-
@RomanKassebaum Possibly of interest to you: https://stackoverflow.com/questions/60114996/implementing-virtualtreeview-tvtdefaultaccessibleprovider-in-c-builder – Coder12345 Feb 17 '20 at 18:37
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++. #include
ing 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.

- 555,201
- 31
- 458
- 770
-
1I 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. – Roman Kassebaum Nov 17 '15 at 11:23
-
@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. – Joachim Marder Nov 17 '15 at 12:20