Skip to main content
All docs
V25.2
  • DevExpress Components in DLL Projects

    • 4 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 dedicated DLL variety called BPL (Borland Package Library). BPLs include 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 when an EXE file loads a BPL package.

    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 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 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 the 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.

    Code Example: Initialize/Finalize a DLL Library

    The following code example calls dxInitialize and dxFinalize procedures to safely load and release a DLL with DevExpress components (my.dll):

    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 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.

    DevExpress Controls in DLL Load Chains

    A loaded DLL can load another DLL, thus forming DLL load chains. DLL load chains impose the same limitations on WinAPI method calls as those applied to a single DLL. Any disallowed call in the DllMain method of any DLL in a chain may result in an application hangup at startup or shutdown.

    Even if you use DevExpress components only in BPL packages, their parent DLLs can indirectly call initialization and finalization routines in their DllMain methods, which may result in application hangups at startup or shutdown. To avoid indirect disallowed calls in DllMain, ensure that your EXE file directly depends on BPLs with DevExpress components or on BPLs that depend on other BPLs with DevExpress components.

    Tip

    You may need to add the following preprocessor directive to all files in a C++Builder project that loads BPL packages in a chain to avoid linker errors: #pragma package(smart_int).

    See Also