Click here to Skip to main content
15,897,371 members
Articles / Programming Languages / C++

Basic C++ Win32 DLL

Rate me:
Please Sign up or sign in to vote.
4.44/5 (27 votes)
26 Sep 2013CPOL4 min read 134.4K   50   25
Basic steps of creating and consuming a C++ Win32 DLL.

Introduction

In this article, we will create a small and simple Win32 C++ DLL project using an Empty Project template from Visual Studio 2010 and then create a separate Win32 Console Application to consume the DLL functionalities.

There are many uses of DLL but this article only focuses on how to create and use a C++ Win32 DLL as well as giving you a skeleton on the structure of a C++ Win32 DLL. A C++ Win32 DLL produces binary code. Note that there is also another kind of DLL which is a CLR DLL. CLR DLL does not produce binary code but it generates an Intermediate Language code or IL code which is not covered in this article. CLR DLLs are called managed code while C++ Win32 DLLs are called unmanaged code. CLR codes are those codes made from .NET Framework languages like C#, VB.NET, or with VC++ .NET.

Background

You can simply think of a DLL or Dynamic Link Library as a collection of codes, data, or resources that is packed together into one file. DLL is a great way to distribute and reuse code. For example you have two applications that use arithmetic operations like Addition, Subtraction, Multiplication, and Division, instead of coding the same operations in each application, you can just put these operations inside a DLL (e.g., Math.dll) and reference the DLL from the two applications. In this manner, you only code the math operations once, while your two applications or even your future applications can use the same Math.dll for arithmetic operations.

More of that, it would be easier to understand if we will just see the working code, right? So let's dive into the code project!

Using the code

First, let's create a C++ Win32 DLL using Visual Studio 2010. (It is recommended to use VS 2010 since this was the actual IDE used to build this project. Other version may be used but with some slight differences.)

Let's open Visual Studio 2010 and select "File > New Project > Visual C++ > Win32 > Win32 Project" and name the new project "MyWin32CppDLL" and then Press OK. A Win32 Application Wizard window will popup - click Next button and then select the Application type: "DLL" and tick Additional options: "Empty project" and finally click the Finish button.

Then let's add four files into our project (MyWin32ClassOne.h, MyWin32ClassOne.cpp, MyWin32ClassTwo.h, and MyWin32ClassTwo.cpp). I just wanted to add two classes into our DLL to illustrate that we can add classes as many as we like into a DLL.

Place the below code to their respective files.

MyWin32ClassOne.h

C++
namespace MyWin32DLL
{
    class MyWin32ClassOne
    {
    private:
        int varone;
    public:
        __declspec(dllexport) MyWin32ClassOne();//constructor
        __declspec(dllexport) void Setvar(int val);
        __declspec(dllexport) int Getvar();
    };
} 

MyWin32ClassOne.cpp

C++
#include "MyWin32ClassOne.h"

namespace MyWin32DLL
{
    MyWin32ClassOne::MyWin32ClassOne()
    {
        varone = 123;
    }
 
    void MyWin32ClassOne::Setvar(int val)
    {
        varone = val;
    }
 
    int MyWin32ClassOne::Getvar()
    {
        return varone;
    }
} 

MyWin32ClassTwo.h

C++
namespace MyWin32DLL
{
    class MyWin32ClassTwo
    {
    private:
        int vartwo;
    public:
        __declspec(dllexport) MyWin32ClassTwo();//constructor
        __declspec(dllexport) void Setvar(int val);
        __declspec(dllexport) int Getvar();
    };
} 

MyWin32ClassTwo.cpp

C++
#include "MyWin32ClassTwo.h"

namespace MyWin32DLL
{
    MyWin32ClassTwo::MyWin32ClassTwo()
    {
        vartwo = 345;
    }

    void MyWin32ClassTwo::Setvar(int val)
    {
        vartwo = val;
    }
 
    int MyWin32ClassTwo::Getvar()
    {
        return vartwo;
    }
}  

Build the project and look for the output DLL in the Debug/Release folder. We have now created our C++ Win32 DLL!

What's the purpose of a DLL if there's no one that uses it, right? So let's create a simple Win32 Console Application that will use our DLL's functionalities.

In Visual Studio, add a new Win32 Console Project as an Empty Project and name it "MyWin32CppApp" and then add a source file named "Main.cpp" just like below.

Add below code to Main.cpp:

Main.cpp

C++
#include<iostream>//for cin, cout and endl
using namespace std;
 
#include "MyWin32ClassOne.h" 
#include "MyWin32ClassTwo.h" 
using namespace MyWin32CppDLL;
 
int main()
{
    cout<<"Hello C++ Win32 DLL"<<endl;
 
    MyWin32ClassOne sc1;
    cout<<"default value of variable from dll : "<<sc1.Getvar()<<endl;
    sc1.Setvar(101);
    cout<<"value of variable from dll : "<<sc1.Getvar()<<endl;
 
    MyWin32ClassTwo sc2;
    cout<<"default value of variable from dll : "<<sc2.Getvar()<<endl;
    sc2.Setvar(200);
    cout<<"value of variable from dll : "<<sc2.Getvar()<<endl;
 
    cin.get();//pause console to see the message

    return 0;
}

Before we can build our application correctly, we need to add a reference to our DLL. Right click the Application project and select "Properties" to open its property page.

First, navigate to "C/C++ > General > Additional Include Directories" then assign the full path where the header files of the DLL are located. This will tell the compiler to locate MyWin32ClassOne.h and MyWin32ClassTwo.h in this location. Click OK.

Second, right click Application project and select "References...". Click "Add New References" and select the DLL project we previously created. Click OK. Finally, build the Solution as Release. Navigate to "Release" folder and launch MyWin32CppApp.exe.

Points of Interest

When we add the path to the header files in our application project, we are just telling the compiler to locate the header files we are using from that location. But when we add reference to our DLL project from our application project, we are basically telling the Linker to link the header files of the actual implementation of our Win32 DLL. 

Advanced points to ponder: 

  •  C++ DLL built from different compilers may not be consumed by a C++ Application/other C++ DLL directly because C++ compilers have different "name mangling" specifications. *This is why we need to compile the source of a C++ DLL project along with our C++ application to ensure they are built using the same compiler.
  • For a C++ DLL to be imported in a C application, global functions.
  • In .NET C#, you can only "DllImport" or "PInvoke" globally exported functions from a C++ DLL.

Hope this helps.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Philippines Philippines
Raw tools of C++ and highly sophisticated C#.Net framework architecture is picture-perfect!

Comments and Discussions

 
QuestionC++ dll on windows Pin
Member 1375317629-Mar-18 2:35
Member 1375317629-Mar-18 2:35 
Questiona suggestion Pin
Southmountain3-Feb-18 9:28
Southmountain3-Feb-18 9:28 
QuestionGood Project type description Pin
Mónica_Cid4-May-17 5:59
Mónica_Cid4-May-17 5:59 
QuestionTypo in Main.CPP file Pin
Member 1226665015-Jan-16 5:58
Member 1226665015-Jan-16 5:58 
QuestionAlmost there Pin
brownpeteg15-Sep-15 1:27
brownpeteg15-Sep-15 1:27 
QuestionPlease include a demo project Pin
Franc Morales1-Apr-14 7:48
Franc Morales1-Apr-14 7:48 
GeneralMy vote of 3 Pin
sandeep00773415-Oct-13 23:06
sandeep00773415-Oct-13 23:06 
Questiontypo Pin
Orlando Selenu7-Oct-13 23:31
Orlando Selenu7-Oct-13 23:31 
SuggestionC++ Win32 DLLs are called unmanaged code ..... Pin
LaxmikantYadav3-Oct-13 20:48
LaxmikantYadav3-Oct-13 20:48 
GeneralRe: C++ Win32 DLLs are called unmanaged code ..... Pin
ThatsAlok7-Oct-13 19:23
ThatsAlok7-Oct-13 19:23 
GeneralRe: C++ Win32 DLLs are called unmanaged code ..... Pin
KarstenK11-Aug-14 7:13
mveKarstenK11-Aug-14 7:13 
Questionstrange order of result according to classes definitions Pin
ersi057130-Sep-13 20:09
professionalersi057130-Sep-13 20:09 
QuestionQuestion Pin
Richard MacCutchan26-Sep-13 0:52
mveRichard MacCutchan26-Sep-13 0:52 
AnswerRe: Question Pin
wembikon26-Sep-13 17:05
wembikon26-Sep-13 17:05 
GeneralRe: Question Pin
Richard MacCutchan26-Sep-13 21:27
mveRichard MacCutchan26-Sep-13 21:27 
GeneralMy vote of 5 Pin
aydinsahin19-Sep-13 4:24
aydinsahin19-Sep-13 4:24 
SuggestionPossible "simplification" Pin
pasztorpisti18-Sep-13 5:33
pasztorpisti18-Sep-13 5:33 
GeneralRe: Possible "simplification" Pin
wembikon18-Sep-13 17:39
wembikon18-Sep-13 17:39 
GeneralRe: Possible "simplification" Pin
giulicard22-Sep-13 23:50
giulicard22-Sep-13 23:50 
GeneralRe: Possible "simplification" Pin
pasztorpisti23-Sep-13 0:24
pasztorpisti23-Sep-13 0:24 
GeneralRe: Possible "simplification" Pin
giulicard23-Sep-13 3:52
giulicard23-Sep-13 3:52 
GeneralRe: Possible "simplification" Pin
pasztorpisti23-Sep-13 4:32
pasztorpisti23-Sep-13 4:32 
Well, lets forget about resource management because it has nothing to do with this topic. In case of DLL you have to take care of resource management regardless of the interface you define.

I never forced using C++ interface but in a C++ only program (especially if the used compiler for the modules is the same or with COM compliance) is a quite viable option. What I emphasized is the single exported function. You can still use a C interface with the technique I've shown.

Using C interface in a C++ program? Preparing for the worst that may never happen isn't always the best way to go especially if you have to sacrifice nice design. I usually use C++ objects to keep my design in a better "shape". Lets say someone wants to use my module from assembly. Its still possible, I've used for example DirectX (COM) several times from both C and assembly and Delphi. Its not only possible but relatively easy. Still, if I have a DLL and someone wants a C interface I can put together an additional C interface layer for him on top of my C++ interface in relatively short time for example in an additional exported function (or several exported functions that I don't like). This way I don't have to sacrifice my object oriented design along the interfaces.

But again, my suggestion was about the single exported function and not about forcing the usage of C++ interfaces in DLLs. Still, my solution is more "portable" even across different compilers than the solution provided by the article itself that introduces problems caused by the incompatible C++ name mangling of different compilers. For example in Visual C++ you would be unable to use even an exe and a DLL together with the article's solution (compiled by the same VC++ compiler!) if they were compiled with different configs (Debug/Release) because the name mangling would differ for Debug/Release! Sometimes using Release DLL even from your Debug builds is reasonable if your don't want to debug the DLL and it performs time consuming work. Each solution has its own list of advantages and disadvantages and people can choose their favorite one.
GeneralRe: Possible "simplification" Pin
giulicard23-Sep-13 5:10
giulicard23-Sep-13 5:10 
GeneralRe: Possible "simplification" Pin
pasztorpisti23-Sep-13 5:22
pasztorpisti23-Sep-13 5:22 
GeneralRe: Possible "simplification" Pin
John Bandela27-Sep-13 4:25
John Bandela27-Sep-13 4:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.