while visiting clients of the company I work on, sometime I still found some applications especially desktop application build on unmanaged code (such as Delphi, Visual Basic 6, C++, etc). Even though at the time of this blog post, many application build on .NET (managed code) on Windows platform. There are various reasons why they do not migrate to managed code which has some advantages over unmanaged code (such as the application still run well with the version of OS they use, rewrite app will need extra cost, etc). This means unmanaged code application is not dead at all for LOB app, even though the percentage is much lower than the managed one.
Maybe this topic seems out of date topic in the .NET era, but at least this post as a note for my self in case I need it on the other day.
While developing an application, usually we want to share some of our code with other application. Dynamic Link Library (DLL) is Microsoft’s implementation of the shared library concept in the Microsoft Windows. The term DLL in this post will refer to unmanaged code and only focus to the one build with Visual C++ compiler on Windows environment.
When we create a DLL, we also create a .lib file that contains information of exported class or functions. When we build an executable that calls the DLL, the linker uses the exported symbols in the .lib file to store this information for the loader. When the loader loads a DLL, the DLL is mapped into the memory space of the executable.
An executable file links to (or loads) a DLL in one of two ways, implicit or explicit linking. In this post will create simple sample both of them how C++ class exported in the two ways. The samples in this post created using IDE Microsoft Visual Studio 2013 Ultimate. To simplify the code, I just created a single solution contains a Win32 DLL project and a console application client. The DLL project contains classes for both sample implicit and explicit linking. Either the console application contains sample code for implicit and explicit linking caller. Here is the classes I use in this sample.
Implicit linking, where the operating system loads the DLL when the executable using it is loaded. The executable client calls the exported functions of the DLL just as if the functions were statically linked and contained within the executable. Implicit linking is sometimes referred to as static load or load-time dynamic linking. Now let’s create a sample of DLL with implicit linking.
First of all, create an empty solution in Visual Studio by selecting
New Project > scroll down on the left pane, expand
Other Project Types >
Visual Studio Solutions select
Black Solution. Fill the solution name as
Now we have an empty solution in Visual Studio. Right click the
VCppDLL solution >
New Project. In the left pane of the New Project dialog box, expand Installed templates
Visual C++, and then select
Win32. Fill the project name as MathWin32DLL, then click OK.
On the Win32 Application Wizard dialog in the
Application Settings part, select
DLL and check
Empty project, then click Finish
Now we have an empty C++ DLL project in the Visual Studio solution. As the class diagram picture above, let create a simple
BaseMath class. Right click the MathWin32DLL project >
Visual C++ template on the left pane dialog, select
C++ Class > click
Add. On the
Generic C++ Class Wizard, fill the
Class name as BaseMath then click
Finish. Edit the
BaseMath.h with the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
We can delete
BaseMath.cpp file since we will make the
BaseMath as an abstract class.
In Visual Studio, by default the New Project template for a DLL adds PROJECTNAME_EXPORTS to the defined preprocessor symbols for the DLL project. We can see the preprocessor symbols definition in
Property Pages of MathWin32DLL project in the
Configuration Properties >
In the code of
MATHWIN32DLL_EXPORTS symbol is defined, the
Math_API symbol is set to
__declspec(dllexport) modifier otherwise it is set to
__declspec(dllexport) modifier can be applied to classes, functions, or variables that tells the compiler and linker to export them from the DLL so that it can be used by other applications.
Meanwhile when we include
BaseMath.h in client project,
Math_API is set to
__declspec(dllimport). This modifier optimizes the import of the exported class in an application.
For the next, let’s create another class called
AddOperationMath. Edit the
AddOperationMath.cpp respectively as follow.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
AddOperationMath inherits from
BaseMath. We also mark the
AddOperationMath class with
Math_API macro that’s defined in
BaseMath.h which means we will expose the
AddOperationMath class in the DLL to executable client application. When we compile the DLL project, we should get a warning
In this case, ideally we should export (mark with
Math_API macro) both
core::AddOperationMath to make the compiler does not fire the warning message.
To complete our sample, let’s create another project called MathWin32ClientConsole as we did the creation of MathWin32DLL project, except select
Console Application instead of
DLL in the
Application Settings dialog.
In the MathWin32ClientConsole project, right click >
New Item. Select
Visual C++ project template on the left pane, then select
C++ File (.cpp). Fill the name with
To make the MathWin32ClientConsole project has reference to MathWin32DLL project, right click MathWin32ClientConsole project >
Properties. Scroll up the
Property Pages dialog, expand
Common Properties on the left pane > select
Add New Reference button, select
Projects and check the
OK. Now you should see
MathWin32DLL added to the
References pane as the following picture.
To make the
AddOperationMath class is recognized in the MathWin32ClientConsole project, we have to include
AddOperationMath.h. We can copy the
BaseMath.h to the MathWin32ClientConsole project. But it is not a good way in our scenario, because if we make changes to one of them, we have to recopy it to the MathWin32ClientConsole project directory. To avoid this manual copy, we can include the MathWin32DLL project directory to the MathWin32ClientConsole so that we can include any header files of MathWin32DLL to MathWin32ClientConsole if needed. To do that open the Property pages of MathWin32ClientConsole, select
Configuration Properties >
General. Select the drop-down control next to the
Additional Include Directories edit box, and then choose
<Edit...>. Select the top pane of the
Additional Include Directories dialog box to enable an edit control. In the edit control, fill
$(SolutionDir)\MathWin32DLL which tells to Visual Studio to scan or search header files that we include in directory
MathWin32DLL inside solution directory.
Now we can include header file defined in
MathWin32ClientConsole. Let create code that call class defined in the DLL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
1 2 3 4
There is no need to explicitly specify a calling convention for exporting classes or their methods. By default, the C++ compiler uses the
__thiscallcalling convention for class methods. However, due to different naming decoration schemes that are used by different compilers, the exported C++ class can only be used by the same compiler and by the same version of the compiler. Only the MS Visual C++ compiler can use this DLL now. Both the DLL and the client code must be compiled with the same version of MS Visual C++ in order to ensure that the naming decoration scheme matches between the caller and the callee
To use a DLL by implicit linking, an executable must include the header files that declare the data, functions or C++ classes exported by the DLL in each source file that contains calls to the exported data, functions, and classes. The classes, functions, and data exported by the DLL must all be marked
__declspec(dllimport) in the header file. From a coding perspective, calls to the exported functions are just like any other function call.
To build the calling executable file, we must link with the import library (.lib). If we use an external makefile or build system, we need to specify the file name of the import library where we list other object (.obj) files or libraries that we link.
The operating system must be able to locate the DLL file when it loads the calling executable. This means that we must deploy or verify the existence of the DLL when our application is installed.
Explicit linking, where the operating system loads the DLL on demand at runtime. An executable that uses a DLL by explicit linking must make function calls to explicitly load and unload the DLL and to access the functions exported by the DLL. Unlike calls to functions in a statically linked library, the client executable must call the exported functions in a DLL through a function pointer. Explicit linking is sometimes referred to as dynamic load or run-time dynamic linking.
To use a DLL by explicit linking, applications must make a function call to explicitly load the DLL at run time. To explicitly link to a DLL, an application must :
LoadLibraryEx, or a similar function to load the DLL and obtain a module handle.
GetProcAddressto obtain a function pointer to each exported function that the application calls. Because applications call the DLL functions through a pointer, the compiler does not generate external references, so there is no need to link with an import library. However, you must have a typedef or using statement that defines the call signature of the exported functions that you call.
FreeLibrarywhen done with the DLL.
To create a sample for explicit linking, we will use an abstract interface (a class with pure virtual methods, and no data) and create a factory method for object instantiation.
On the MathWin32DLL create a new class called
LogarithmicMath. Edit the header and implementation files as follow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
Next, create a
Factory class that encapsulates
LogarithmicMath instantiation and will be called from client app.
1 2 3 4 5
1 2 3 4 5 6 7 8 9
We can see that the
LogarithmicMath class look like a standard C++ class. Instead of directly export the
LogarithmicMath class, we use
Factory that handle the export technics.
extern "C" which tells the C++ compiler that the linker should use the C calling convention. It is required in order to prevent the mangling of the function name. So, this function is exposed as a regular C function, and can be easily recognized by any C-compatible compiler. The name itself is exported from the DLL unmangled (
Math_API tells the linker to export the
CreateLogarithmicMath method from the DLL.
__cdecl is the default calling convention for C and C++ programs.
Now let create a sample code in the MathWin32ClientConsole by editing the
Main.cpp as following.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
Now build and run the MathWin32ClientConsole, we should get the following output.
1 2 3 4 5 6 7 8 9
In order to ensure proper resource release, an abstract interface provides an additional method for the disposal of an instance. In this case we provide
Destroy method. Calling this method manually can be tedious and error prone. It’s recommend use smart pointer for auto resource release instead of manual release.
The code of this article can be found here