Skip to content

guyllaumedemers/MSVC-Building-a-library

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MSVC, Building a library

Using libraries and why it matters.

Wikipedia : "The value of a library lies in the reuse of standardized program elements. When a program invokes a library, it gains the behavior implemented inside that library without having to implement that behavior itself. Libraries encourage the sharing of code in a modular fashion and ease the distribution of the code."

Project

Example details are grouped into subject related points and showcase investigation result on the subject of libraries. Further details will be provided on more advance features that are covered in the making of our examples.

What this README.md is not

Be aware that some of the tooling used in the making of this Demo project won't be covered here. External documentations will be provided for your own benefit, which in most case, are also where most of the information mentioned here will be coming from.

Quick guide to CLI (Command-line Interface)

  • cl : The compilers produce Common Object File Format (COFF) object (.obj) files. The linker produces executable (.exe) files or dynamic-link libraries (DLLs). To compile without linking, use the /c option.
  • lib : The Microsoft Library Manager (LIB.exe) creates and manages a library of Common Object File Format (COFF) object files. LIB can also be used to create export files and import libraries to reference exported definitions.
  • link : LINK.exe links Common Object File Format (COFF) object files and libraries to create an executable (EXE) file or a dynamic-link library (DLL).
  • dumpbin : The Microsoft COFF Binary File Dumper (DUMPBIN.EXE) displays information about Common Object File Format (COFF) binary files. You can use DUMPBIN to examine COFF object files, standard libraries of COFF objects, executable files, and dynamic-link libraries (DLLs).

What's a library

Wikipedia : "A library is a collection of implementations of behavior, written in terms of a language, that has a well-defined interface by which the behavior is invoked. For instance, people who want to write a higher-level program can use a library to make system calls instead of implementing those system calls."

Calling Conventions and Symbols

Wikipedia : "A calling convention is an implementation-level (low-level) scheme for how subroutines or functions receive parameters from their caller and how they return a result. When some code calls a function, design choices have been taken for where and how parameters are passed to that function, and where and how results are returned from that function, with these transfers typically done via certain registers or within a stack frame on the call stack."

  • __cdecl : Is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code.
  • extern "C" : Makes a function-name in C++ have C linkage (compiler does not mangle the name) so that client C code can link to (use) your function using a C compatible header file that contains just the declaration of your function.
  • __declspec : Adds the export directive to the object file so you do not need to use a .def file.

Types of libraries

Header-only library

A library is called header-only if the full definitions of all macros, functions and classes comprising the library are visible to the compiler in a header file form. Header-only libraries do not need to be separately compiled, packaged and installed in order to be used.

Example - MSVC Development Toolkit Cmd-line
C:> cl Main.cc		(Main.obj, Main.exe)
// header-only library

#include <type_traits>

class FMath {
public:
	template<typename T,
		std::enable_if_t<std::is_arithmetic<T>::value, bool> = true>
	inline static T Sum(const T A, const T B) {
		return A + B;
	}
};

// executable

#include <stdio.h>
#include "Math.hh"

int main(int argc /*arg count*/, char* argv[] /*arg values*/) {

	printf("%i",  FMath::Sum<int  >(1    , 2    ));
	return 0;
};

Static library

A static library or statically-linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable.

Example - MSVC Development Toolkit Cmd-line
C:> cl /c HelloWorld.cc				(HelloWorld.obj)
C:> lib HelloWorld.obj				(HelloWorld.lib)
C:> cl Main.cc /link HelloWorld.lib		(Main.obj, Main.exe)

Tips : Now that the executable has been compiled and linked with the static library (.lib), the executable can invoke functions defined in the static library without the .lib existing as its now compiled into the executable. You can safely delete the .obj file and .lib file and run the executable.

// static library

extern "C" const char* __cdecl Print() {
	return "Hello World!";
}

// executable

#include <stdio.h>

// forward declaration
extern "C" const char* __cdecl Print();

int main(int argc /*arg count*/, char* argv[] /*arg values*/) {

	puts(Print());
	return 0;
};

Shared library

A shared library or shared object is a file that is intended to be shared by executable files and further shared object files. Modules used by a program are loaded from individual shared objects into memory at load time or runtime, rather than being copied by a linker when it creates a single monolithic executable file for the program.

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.

Example A - MSVC Development Toolkit Cmd-line
C:> cl /c GetGreetings.cc			(GetGreetings.obj)
C:> link GetGreetings.obj /DLL /NOENTRY		(GetGreetings.lib, GetGreetings.exp, GetGreetings.dll)
C:> cl Main.cc /link GetGreetings.lib		(Main.obj, Main.exe)

What's an .exp and why should we care : The DLL won't link until the executable is built to provide a .lib file -- but the executable won't link until the DLL is built to provide a .lib file. To break the dependency, you run the linker against the executable, which fails (because it can't find a .lib file for the DLL), but will produce a .exp file. You then link the DLL against the .exp file for the executable. You can then re-run link to produce the executable, using the .lib file for the DLL.

// shared library

__declspec(dllexport) const char* __cdecl GetGreetings() {
	return "Greatings Programmer!";
}

// executable

#include <stdio.h>

__declspec(dllimport) const char* __cdecl GetGreetings();

int main(int argc /*arg count*/, char* argv[] /*arg values*/) {

	puts(GetGreetings());
	return 0;
};

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.

Example B - MSVC Development Toolkit Cmd-line
C:> cl /c GetGreetings.cc					(GetGreetings.obj)
C:> link GetGreetings.obj /DLL /NOENTRY	/EXPORT:GetGreetings	(GetGreetings.lib, GetGreetings.exp, GetGreetings.dll)
C:> cl Main.cc							(Main.obj, Main.exe)
// shared library

extern "C" const char* __cdecl GetGreetings() {
	return "Greatings Programmer!";
}

// executable

#include <stdio.h>
#include <Windows.h>

int main(int argc /*arg count*/, char* argv[] /*arg values*/) {

	const HMODULE ModuleHandle = LoadLibraryExW(L"GetGreetings.dll", nullptr, 0);
	using GetGreetingType = const char* (__cdecl*)();
	const GetGreetingType GetGreetings = reinterpret_cast<GetGreetingType>(GetProcAddress(ModuleHandle, "GetGreetings"));

	puts(GetGreetings());
	FreeLibrary(ModuleHandle);
	return 0;
};

Tips : Further details are provided regarding window's specific usage of dll's at the following link. Additional information about Dll can be found on cppcon channel.

Releases

No releases published

Packages

No packages published

Languages