DevExpress Components in DLL Projects
- 3 minutes to read
Any component always safely allocates and releases required system resources (such as memory, handles, context, etc.) when used in a built executable file (EXE). However, if a component is used in a dynamic link library (DLL) project, the component’s initialization and finalization routines can be called safely only at specific moments.
Tip
Embarcadero RAD Studio® allows you to build a special DLL variety called BPL (Borland Package Library). A BPL is a special DLL variety with RAD Studio-specific code designed for use in Delphi and C++Builder projects. This automatically added code ensures that all component initialization and finalization routines are called safely.
We recommend that you use DevExpress components in BPL projects instead of DLL projects if you need dynamic link libraries in your application.
How to Use a DevExpress Component in a DLL
Every DevExpress unit in a project adds its initialization and finalization routines to the global lists executed automatically and safely in a built EXE or BPL file. In a DLL, the DllMain
method (the DLL entry point) initializes and finalizes all units used in the DLL. The DllMain
method imposes multiple limitations on WinAPI method calls as described in the following Microsoft documentation topic: Dynamic-Link Library Best Practices. The majority of DevExpress units does not comply with these limitations. Therefore, it is impossible to use DevExpress components in DLL projects in the same way as in other project types.
If you need to use dynamic link libraries in an application and you cannot build BPL files with DevExpress components for any reason, the dxInitialize and dxFinalize procedures allow you to use DevExpress components in a DLL project safely. These procedures execute the global initialization and finalization routines for all DevExpress units in a DLL project.
Call the dxInitialize procedure once an application loads a DLL with DevExpress components before an application attempts to use the components for the first time. Call the dxFinalize procedure when the application is about to unload the previously loaded DLL to properly release all system resources used by DevExpress controls in the DLL.
Example
The following code example illustrates how to call the dxInitialize and dxFinalize procedures in an application project that uses a DLL with one or more DevExpress components:
procedure TMyForm.MyProcedure;
type
TRoutine = procedure(); stdcall;
var
ALibrary: THandle;
AInitializeProc, AFinalizeProc: TRoutine;
begin
ALibrary := LoadLibrary('my.dll');
if ALibrary = 0 then
raise Exception.Create('Could not load the library');
try
// The InitializeDXLibrary method calls the dxInitialize procedure within the my.dll library
AInitializeProc := TRoutine(GetProcAddress(ALibrary, 'InitializeDXLibrary'));
if not Assigned(AInitializeProc) then
raise Exception.Create('Improper library version');
// The FinalizeDXLibrary method calls the dxFinalize procedure within the my.dll library
AFinalizeProc := TRoutine(GetProcAddress(ALibrary, 'FinalizeDXLibrary'));
if not Assigned(AFinalizeProc) then
raise Exception.Create('Improper library version');
AInitializeProc;
try
// All code that works with DevExpress components within my.dll goes here
finally
AFinalizeProc;
end;
finally
FreeLibrary(ALibrary);
end;
end;
Important
Do not call the dxInitialize and dxFinalize procedures in the initialization and finalization sections of a DLL project, respectively. Otherwise, an application may hang on loading or unloading the built DLL.