Creating a DLL Using CBuilder

   

Creating a DLL Using C++Builder

In this first section, we'll look at how to create a DLL using C++Builder. The simplest way to create a DLL is with the C++Builder's DLL Wizard. You can also create a DLL from scratch almost as easily, simply by starting with a blank header and c or cpp source file.

The primary function that needs to be included in the source of a DLL file is a main entry function. Within the world of Microsoft ( specifically Visual C++), this function is called DLLMain() .

 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)  {          return 1;  } 

Within the world of Borland (specifically C++Builder and its precursor C++), this function is called DLLEntryPoint() .

 int WINAPI DllEntryPoint(HINSTANCE hinst,                        unsigned long reason,                        void* lpReserved)  {          return 1;  } 

Borland C++Builder Version 6 now also supports the DLLMain() entry function.

TIP

If you're a developer who uses both C++Builder and Visual C++, the DLLMain() entry point function will allow greater compatibility between these two development environments.


At this point, after a main entry function is in place, you can begin to add the functionality you want to share through a DLL. We'll develop an example shortly, but let's first look at the DLL Wizard, which will shed some light on the different types of DLLs that can be created and supported by C++Builder.

Using the DLL Wizard

The DLL Wizard can be brought up within C++Builder by selecting File, New, and Other from the main menu, and then selecting the DLL Wizard from the New tab of the New Items dialog. The DLL Wizard provides several options for you to choose from (see Figure 16.1).

Figure 16.1. The following options are presented on the DLL Wizard dialog box.

graphics/16fig01.gif

Source Type:

C This specifies that the C language will be used as the source type, which allows access to the Multi Threaded, and VC++ Style DLL options. The Use VCL and Use CLX options are disabled because VCL and CLX are object-oriented classes and can only be included in a C++ project.

C++ This specifies that the C++ language will be used as the source type, which enables access to the Use VCL , Use CLX , Multi Threaded , VC++ Style DLL options, as well as the use of object-oriented classes. If this option is chosen , the compiler will use C++ to compile the code in the main module of the DLL, thus enabling you to use C++ code in your DLL.

Options:

Use VCL This option creates a DLL that can contain VCL components and classes. This causes C++Builder to include the VCL.h file in your main module, and changes the startup code and linker options for compatibility with VCL objects. You will also notice that the Multi Threaded option becomes checked and disabled. The reason for this is because the VCL needs to have multithreading capabilities.

Use CLX This option creates a DLL that can contain CLX components and classes. This causes C++Builder to include the clx.h file in your main module and changes the startup code and linker options for compatibility with CLX objects. You will also notice that the Multi Threaded option becomes checked and disabled. The reason for this is because the CLX needs to have multithreading capabilities.

Multi Threaded This option specifies that the DLL will have more than one thread of execution, so if you plan to have multiple threads in your DLL, it would be a good idea to choose this option. Remember that the VCL and CLX need to have this capability, so if you manually try to add components into the DLL later and didn't check this, you may run into a problem. To avoid this, always make sure that this option is checked.

VC++ Style DLL This option specifies what type of entry point the DLL is going to have. If you want the DLL entry point to be DLLMain() , the Visual C++ style, check the VC++ style option; otherwise , DLLEntryPoint() is used for the entry point function. The choice is up to you.

After you have made your selections and clicked OK, C++Builder will automatically generate a skeleton DLL application. The only function that it creates in the source file, however, is an empty entry point function, DLLMain() or DLLEntryPoint() , which depends on the selection of VC++ Style DLL .

When you use the Wizard, it will create several files for you. A source file that ends in either *.c or *.cpp , a Resource file that ends in *.res , and a Borland Project File called a *.bpf . This is illustrated in Figure 16.2. In most cases, the only file that really matters is the source file. In fact, when you build a DLL from scratch, not using the Wizard, you'll often create a source file and an associated header file. Because the Wizard doesn't create the header file, you might need to create it as well. Typically, we use a header file to expose the functionality of the DLL to other applications.

Figure 16.2. A project generated from the DLL Wizard.

graphics/16fig02.gif

Filling in DLL Code

Let's go ahead and fill in some code for our entry point function so that we can begin to fully understand how a DLL works, as shown Listing 16.1.

Listing 16.1 The DLL Entry Point Function
 bool WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID lpvReserved)  {      switch(fwdreason)      {      case DLL_PROCESS_ATTACH:              if (lpvReserved)                    MessageBox(NULL,"Process has attached to DLL (Static Load)",                        "DLLMain",MB_OK);              else                    MessageBox(NULL,"Process has attached to DLL (Dynamic Load)",                          "DLLMain",MB_OK);              break;      case DLL_THREAD_ATTACH:              MessageBox(NULL,"Thread has attached to DLL","DLLMain",MB_OK);              break;      case DLL_THREAD_DETACH:              MessageBox(NULL,"Thread has detached to DLL","DLLMain",MB_OK);              break;      case DLL_PROCESS_DETACH:              MessageBox(NULL,"Process has detached to DLL","DLLMain",MB_OK);              break;      }      return 1; // always return true;  } 

In this example, our DLL examines the activity associated to the application loading (or unloading) the DLL. Three parameters can be examined within the main entry function. The first parameter, hinstDLL , identifies the handle of the DLL. The second parameter, fwdReason , identifies the type of activity associated to the process or thread loading or unloading. The third parameter, lpvReserved , is NULL if the DLL was dynamically loaded or non-NULL if the DLL was statically loaded (we will discuss DLL loading in a moment). The value we're most interested in is fwdReason . By knowing the action, whether a process or thread is coming or going, we can have the DLL initialize its variables on entry, and destroy existing pointers and threads on exit.

We need to add some functionality to our DLL so that the DLL is useful to outside applications. For starters, let's add a function to the simple.c file that identifies the version of the DLL, and provides some metric conversion, as shown in Listing 16.2.

Listing 16.2 Examples of DLL Functions
 const double version = 1.1;  double simpleGetLibVersion()  //the current library version of the DLL.  {      return version;  }  //                                      - double feet_to_meters(double feet)  {      return (feet * 0.3048);  }  //                                      - double meters_to_feet(double meters)  {      return (meters * 3.2808);  } 

Notice a constant identifying the version is included, which is used by the simpleGetLibVersion() function. When an application calls this DLL function, the DLL version as identified by the version variable will be returned. When an application calls the feet_to_meters() function, the value identified by the feet parameter will be converted and returned as meters. Inversely, when an application calls meters_to_feet() function, the value identified by the meters parameter will be converted and returned as feet.

Adding a DLL Header File

To make the function available to an application that loads the DLL, we need to create a header file that exposes the function. This is shown in Listing 16.3.

Listing 16.3 The DLL Header File
 #ifndef __SIMPLE_H  #define __SIMPLE_H  #if defined(__cplusplus)  extern "C"  {  #endif  __declspec(dllexport) double simpleGetLibVersion();  __declspec(dllexport) double feet_to_meters(double feet);  __declspec(dllexport) double meters_to_feet(double meters);  #if defined(__cplusplus)  }  #endif  #endif // __SIMPLE_H 

This header file provides the basis for the DLL interface. The _cplusplus constant is defined if C++Builder is compiling C++ code. In this example, we are compiling C source code because our source file has a c extension, therefore the extern "C" clause will be ignored on compilation. Otherwise, if we were compiling C++ code, the extern keyword tells C++Builder to use the C calling convention. Any compiler that supports C-type exports will be able to import this function.

In this example, we also use the declspec(dllexport ) storage class specifier preceding each function. This clause enables you to export functions, data, and objects from a DLL. In our example, we export a function that we want to be able to call from any application that loads the DLL. Furthermore, this clause provides compatibility of our DLL with Microsoft C/C++ applications and eliminates the need for a module-definition ( .DEF ) file.

Building a DLL

A DLL is built much the same way an EXE application is built within the C++Builder IDE. For example, the simple.dll example, provided on the CD-ROM that accompanies this book, is built by selecting Project, Build simple, as illustrated in Figure 16.3.

Figure 16.3. Building the simple.dll project using C++Builder.

graphics/16fig03.gif

When the DLL is compiled and linked, C++Builder will generate not only a DLL file, but also a LIB file. The LIB file makes it convenient for a C++Builder application to utilize a DLL by simply identifying the LIB file as part of the application's project. This is discussed further in the "Loading a DLL" section.


   
Top


C++ Builder Developers Guide
C++Builder 5 Developers Guide
ISBN: 0672319721
EAN: 2147483647
Year: 2002
Pages: 253

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net