RAD Studio |  |

Creating DLLs Containing VCL Components (C++)

One of the strengths of DLLs is that a DLL created with one development tool can often be used by application written using a different development tool. When your DLL contains VCL components (such as forms) that are to be used by the calling application, you need to provide exported interface routines that use standard calling conventions, avoid C++ name mangling, and do not require the calling application to support the VCL libraries in order to work. To create VCL components that can be exported, use runtime packages.

For example, suppose you want to create a DLL to display the following simple dialog box:

The code for the dialog box DLL is as follows:

Copy Code

    // DLLMAIN.H
    //---------------------------------------------------------------------
    #ifndef dllMainH
    #define dllMainH
    //---------------------------------------------------------------------
    #include <Classes.hpp>
    #include <vcl\Controls.hpp>
    #include <vcl\StdCtrls.hpp>
    #include <vcl\Forms.hpp>
    //---------------------------------------------------------------------
    class TYesNoDialog : public TForm
    {
        __published:    // IDE-managed Components
            TLabel *LabelText;
            TButton *YesButton;
            TButton *NoButton;
            void __fastcall YesButtonClick(TObject *Sender);
            void __fastcall NoButtonClick(TObject *Sender);
        private:        // User declarations
            bool returnValue;
        public:         // User declarations
            virtual __fastcall TYesNoDialog(TComponent *Owner);
            bool __fastcall GetReturnValue();
    };
    // exported interface function
    extern "C" __declspec(dllexport) bool InvokeYesNoDialog();
    //---------------------------------------------------------------------
    extern TYesNoDialog *YesNoDialog;
    //---------------------------------------------------------------------
    #endif
    // DLLMAIN.CPP
    //---------------------------------------------------------------------
    #include <vcl\vcl.h>
    #pragma hdrstop
    #include "dllMain.h"
    //---------------------------------------------------------------------
    #pragma resource "*.dfm"
    TYesNoDialog *YesNoDialog;
    //---------------------------------------------------------------------
    __fastcall TYesNoDialog::TYesNoDialog(TComponent *Owner)
        : TForm(Owner)
    {
        returnValue = false;
    }
    //---------------------------------------------------------------------
    void __fastcall TYesNoDialog::YesButtonClick(TObject *Sender)
    {
        returnValue = true;
        Close();
    }
    //---------------------------------------------------------------------
    void __fastcall TYesNoDialog::NoButtonClick(TObject *Sender)
    {
        returnValue = false;
        Close();
    }
    //---------------------------------------------------------------------
    bool __fastcall TYesNoDialog::GetReturnValue()
    {
        return returnValue;
    }
    //---------------------------------------------------------------------
    // exported standard C++ interface function that calls into VCL
    bool InvokeYesNoDialog()
    {
        bool returnValue;
        TYesNoDialog *YesNoDialog = new TYesNoDialog(NULL);
        YesNoDialog->ShowModal();
        returnValue = YesNoDialog->GetReturnValue();
        delete YesNoDialog;
        return returnValue;
    }
    //---------------------------------------------------------------------

The code in this example displays the dialog and stores the value true in the private data member returnValue if the "Yes" button is pressed. Otherwise, returnValue is false. The public GetReturnValue() function retrieves the current value of returnValue.

To invoke the dialog and determine which button was pressed, the calling application calls the exported function InvokeYesNoDialog(). This function is declared in DLLMAIN.H as an exported function using C linkage (to avoid C++ name mangling) and the standard C calling convention. The function is defined in DLLMAIN.CPP.

By using a standard C function as the interface into the DLL, any calling application, whether or not it was created with RAD Studio, can use the DLL. The VCL functionality required to support the dialog is linked into the DLL itself, and the calling application does not need to know anything about it.

Note: When creating a DLL that uses the VCL, the required VCL components are linked into the DLL resulting in a certain amount of overhead. The impact of this overhead on the overall size of the application can be minimized by combining several components into one DLL that only needs one copy of the VCL support components.

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!