Develop and Use DLL file in Windows.

Prince Pereira
5 min readAug 2, 2023

DLL:
Short for Dynamic Link Library, is a library that contains code and data that can be used by more than one program at the same time.

The two methods of linking to call exported DLL functions: load-time dynamic linking and run-time dynamic linking.

Load-time dynamic linking:
In load-time dynamic linking, an application makes explicit calls to exported DLL functions like local functions. To use load-time dynamic linking, provide a header (.h) file and an import library (.lib) file when you compile and link the application. When you do this, the linker will provide the system with the information that is required to load the DLL and resolve the exported DLL function locations at load time.

Run-time dynamic linking:
In run-time dynamic linking, an application calls either the LoadLibrary function or the LoadLibraryEx function to load the DLL at run time. After the DLL is successfully loaded, you use the GetProcAddress function to obtain the address of the exported DLL function that you want to call. When you use run-time dynamic linking, you do not need an import library file.

Create DLL

Project Name: MyDllLibrary

Right Click “MyDllLibrary” project in Solution Explorer -> Add -> New Item

Select “Header File” -> File Name: “MyDllLibrary.h” -> Add

Copy the below source code to new header file “MyDllLibrary.h” created and Save.

#pragma once

#ifdef MYDLLLIBRARY_EXPORTS
#define MYDLLLIBRARY_API __declspec(dllexport)
#else
#define MYDLLLIBRARY_API __declspec(dllimport)
#endif

extern "C" MYDLLLIBRARY_API void hello_world();

extern "C" MYDLLLIBRARY_API int multiply(int a, int b);

Right Click “MyDllLibrary” project in Solution Explorer -> Add -> New Item -> Select “C++ File” -> File Name: “MyDllLibrary.cpp” -> Add

Copy the below source code to new CPP file “MyDllLibrary.cpp” created and Save.

#include "pch.h"
#include <utility>
#include <limits.h>
#include "MyDllLibrary.h"
#include <iostream>

void hello_world()
{
std::cout << "Hello World .." << std::endl;
}

int multiply(int a, int b)
{
return a * b;
}

Build the library : “Build” -> “Build Solution” and you will see the build success as below.

DLL will be generated in “[Project Root]\x64\Debug\MyDllLibrary.dll”

Create a console client app

New Project Name: MyDllClient

Changes needed for Load-time dynamic linking:

“Project Name: MyDllClient” -> C/C++ -> General -> “Additional Include Directory” > Edit ->

New folder -> Edit

Select Project folder

OK

Add “C:\Users\ppereira\CPPProjects\MyDllLibrary\$(intDir)”

Build Events” -> “Post-Build Event” -> “Command Line” -> xcopy /y /d “C:\Users\ppereira\CPPProjects\MyDllLibrary\$(IntDir)MyDllLibrary.dll” “$(OutDir)” -> Apply -> Ok

Copy following code to “MyDllClient.cpp”

#include <iostream>
#include "MyDllLibrary.h"

using namespace std;

int main()
{
int a = 10, b = 20;

cout << "Main started." << endl;

hello_world();

int res = multiply(a, b);

cout << "Result : " << endl;

cout << "Main completed." << res << endl;

}

Run the application : Local Windows Debugger

Output:

Changes needed for Run-time dynamic linking:

Copy MyDllLibrary.dll from “C:\Users\ppereira\CPPProjects\MyDllLibrary\x64\Debug\MyDllLibrary.dll” to MyDllClient project path.

Make code changes in MyDllClient.cpp

#include <iostream>
#include <windows.h>
#include <stdio.h>


typedef void(__cdecl* FuncNoArgRetVoid)();
typedef int(__cdecl* FuncIntArgRetInt)(int, int);

int main(void)
{
std::cout << "Main started!\n";

HINSTANCE hinstLib;
FuncNoArgRetVoid FuncHelloWorld;
FuncIntArgRetInt FuncMultiply;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

// Get a handle to the DLL module.

hinstLib = LoadLibrary(TEXT("MyDllLibrary.dll"));

// If the handle is valid, try to get the function address.

if (hinstLib != NULL)
{
std::cout << "Load MyDllLibrary.dll passed!\n";

FuncHelloWorld = (FuncNoArgRetVoid)GetProcAddress(hinstLib, "hello_world");

// If the function address is valid, call the function.

if (NULL != FuncHelloWorld)
{
std::cout << "Load hello_world function passed!\n";
fRunTimeLinkSuccess = TRUE;
(FuncHelloWorld)();
}
else
{
std::cout << "Load hello_world function failed!\n";
}

FuncMultiply = (FuncIntArgRetInt)GetProcAddress(hinstLib, "multiply");
if (NULL != FuncMultiply)
{
std::cout << "Load multiply function passed!\n";
fRunTimeLinkSuccess = TRUE;
int result = (FuncMultiply)(10, 25);
std::cout << "Multiply 10, 25 gives : " << result << std::endl;
}
else
{
std::cout << "Load multiply function failed!\n";
}


// Free the DLL module.

fFreeResult = FreeLibrary(hinstLib);
}
else
{
std::cout << "Load MyDllLibrary.dll failed!\n";
}

// If unable to call the DLL function, use an alternative.
if (!fRunTimeLinkSuccess)
printf("Message printed from executable\n");

return 0;

}

Run the application : Local Windows Debugger

Output:

References:

How-To Create And Use A DLL (Dynamic Link Library) with C++ MSVC Visual Studio 2019 Walkthrough — YouTube
Using Dynamic-Link Libraries — Win32 apps | Microsoft Learn

--

--

Prince Pereira

Senior Software Engineer - Microsoft | SDN | Java | Golang | DS & Algo | Microservices | Kubernetes | Docker | gRPC & Protocol Buffer