Create a Standard DLL with VC++

This tutorial is about how to put some of your C++ program's functionality into a standard DLL, and how to make working with the EXE and the DLL simple and seamless. We'll be using Microsoft Visual Studio 2008 and we will cut out the noise; that is, the end result will include a minimum of source code files so that you can tell what's important and what's not. We will create a VS Solution that contains two projects. You will be able to work with both or either easily, single-stepping with the debugger from the EXE code into the DLL code and back.

First a couple of definitions:

Standard DLL
This is the 'old' type of DLL (Dynamic Link Library) -- the foundational type of code module used in Windows and going back to OS/2 of 1985. Whenever you access a Win32 API -- or tap the OS for any common service -- you are calling a function in a DLL. Whenever you want to be able to reuse some code in multiple programs and/or split-off a logical chunk of functionality from your main C++ application, this is where you want to go.

ActiveX DLL
This is a DLL that exposes one or more COM interfaces and needs to be registered before use. Visual Basic programmers tend to think of these when they hear the word, "DLL," but we will not be addressing this type of DLL at all today.

Tutorial method:
Rather than walk you through the VS AppWizard, I'm going to show you how to do most of the setup work with a simple text editor, like NotePad. My reason is that when you use the AppWizard, it does a lot of "hidden" stuff for you. The end result is a tree of "What's this all about?"- type #include files and hidden settings that make the process seem more complicated than it really is.

Plan Ahead
We are envisioning a system in which we may eventually write multiple DLLs and multiple applications that access some or all of these DLLs. We want to be able to add DLLs and add EXEs as needed in a logical framework. We want to create a Visual Studios Solution that fits that image.

The DLL and the EXE will each have a folder for source code -- so each will be self-contained and easy to work with. Let's go ahead and create some folders. Use the Windows Explorer to create a "Master" folder and below it, a folder for the DLL and the EXE:
Next, let's make a plan for the DLL. We need to define its API (Application Programming Interface). What will it do? What functions will it expose? We'll make this simple. Our API will provide just two functions:AddTwoNumbersShowNumber

I personally like to use exported function names with a unique prefix -- so I can tell at a glance where the function is. We'll use MYDLL_ at the start of these function.

Create source code files for the DLL

We're going to create a .h header file that will be used by both the EXE and the DLL. In the MyProgMaster\MyDLL folder, create this file:

A .DEF file can be used to identify the Exports. It's optional (the complier can handle this for you) but we'll use one here because it's easy to do and provides some direct visible control over what's going on. Create this file, also in the MyProgMaster\MyDLL folder.

Now our directory structure looks like this: Create the Project
Now everything is set to have Visual Studio create the DLL project. Use the menu command:

File > New > Project From Existing Code...

Click Next, then enter the project location (the MyDLL directory) and set the name to MyDLLPress Next, then set the Project type to Dynamically linked library (DLL) projectClick Finish

Go ahead and compile the DLL. On my system it shows a single warning error but compiles without error. The warning is related to an option that the "Create from Files" wizard inserted. You can ignore it (or fix it by going to Properties / Configuration / C++ / Detect 64-bit Portability issues).

Create source code files for the EXE
Now we need to create the EXE program so we can exercise the DLL. As before, we'll start by creating the source code, then let VS create a project from it. Create these two files:

The wizard has set the Solution name to be the same as the project. But for organizational purposes, we want this two-project Solution to have a different name. Right-click the Solution name and select Rename and set it to MyProgMaster

Now Add the DLL project that we created earlier. Right-click the MyProgMaster solution name and select
Add > Existing Project...
And browse to locate the MyDLL.vcproj file.
Click Open. Now all the players are in place:Whenever we build the EXE, we want to make sure that the DLL also gets built -- if it has been changed recently. So...

(Note: That also helps the linker find the DLL's .LIB file when it generates the EXE.)

Now Build the Solution (press F7). It builds without error. But when you run the EXE, you will get an ugly popup messages:

The application has failed to start because MyDll.dll was not found...

No Problem! DLLs are Dynamically Linked -- at runtime -- and the Operating System needs to be able to find them. Our DLL should be in the same directory as the EXE (or in the search path). We could just manually copy the DLL into the right directory, but that's no good -- the DLL will keep changing as we develop the project. So we just set Visual Studio to output the DLL into the EXE's directory:

Run the Solution (VS will rebuild it, and put the DLL in the right place) and this time it runs without error.
Go ahead and try some source code changes. Modify the message in the MYDLL_ShowNumber function. Add some new functions to the API header file, the .DEF file, and the DLL CPP source file then try them out from the EXE. Debug the program and put a breakpoint in the MyApp's main function. When you single-step, you will step right into the DLL source code. If you put a breakpoint in the DLL, then when you run the EXE, the debugger will stop exactly as desired.

Conclusion
We now have a Solution that includes two projects -- a console application and a minimal Standard DLL. You can modify the DLL code and then when you debug the EXE, the new code will be in use. If you modify the Application program, the DLL will only be rebuilt if it has changed. Debugging is a breeze -- you can step seamlessly from DLL to EXE and place breakpoints as needed.

Some post-publishing notes:

In the Release version of the project, be sure to change the output directory for the DLL to set it into the Release folder for the EXE

I intentionally omitted the UNICODE-awareness stuff such as T_CHAR (rather than char) and TEXT("Hello World!") (rather than just "Hello World!"). I wanted to present the simplest possible scenario, and I've always found stuff like that to be unnecessarily distracting in a tutorial.

The MYDLL_EXPORTS and MYDLL_API macros constitute a standard combination in these EXE+DLL scenarios. The "Create From Files" Wizard automatically added /D MYDLL_EXPORTS to the DLL project settings. The result is that when #include'd in the DLL, MYDLL_API declares the function as an Export, but when #include'd in the EXE, it just declares an external function to be resolved by the linker.

In doing some experiments, I got stuck once when the compiler thought that MYDLL_EXPORTS was defined when it was working with the EXE code. If that happens, (you get some inscrutable errors on those lines of code) you can fix things up by changing the Properties for the EXE; it's in Configuration / C++ / Advanced / Undefine Preprocessors Definitions.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=If you liked this article and want to see more from this author, please click the Yes button near the:
Was this article helpful?
label that is just below and to the right of this text. Thanks!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel.
Part 1 of this series discussed basic error handling code using VBA.
http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…