Creating DLLs Containing VCL Components (C++)

From RAD Studio
Jump to: navigation, search

Go Up to Creating Packages and DLLs


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 more information, see Working with Packages and Components - Overview.

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

CB6 DevelopersGuide EN img 4.png

The code for the dialog box DLL is as follows:

// 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 C++Builder, 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 that 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.

See Also