The purpose of this sharing isThe purposeto let everyone learn how to create and use static libraries and dynamic libraries, understand the differences between static libraries and dynamic libraries, and know how to choose when using them. We will not go deep into the underlying formats and memory layouts of static libraries and dynamic libraries. For those interested, we recommend a book: "Self-Cultivation of Programmers - Linking, Loading, and Libraries".

1. What is a Library

A library is written, existing, mature code that can be reused.In reality, every program depends on many basic underlying libraries. It is impossible for everyone to write code from scratch. Therefore, the existence of libraries is of extraordinary significance.。

Essentially, a library is a binary form of executable code that can be loaded into memory by the operating system and executed. There are two types of libraries: static libraries (.a, .lib) and dynamic libraries (.so, .dll).

The so-called static and dynamic refer to linking. Let's review the steps to compile a program into an executable:

clip_image002[4]

Figure: Compilation Process

2. Static Libraries

It is called a "static library" because during the linking stage, the object files .o generated by assembly are linked and packaged together with the referenced libraries into the executable file. Therefore, the corresponding linking method is called static linking.

Think about it: a static library is linked together with object files generated by assembly into an executable, so the static library must be similar in format to .o files. In fact, a static library can be simply viewed asa group of object files (.o/.obja collection of files)That is, a file formed by compressing and packaging many object files. Summary of static library characteristics:

- Static library linking to function libraries is completed at compile time.

- At runtime, the program has nothing to do with the function library, making porting convenient.

- Wastes space and resources, because all related object files and involved function libraries are linked together into a single executable file.

Below, we write some simple C++ classes for basic arithmetic operations, compile them into a static library for others to use. The header file is as follows:

StaticMath.h header file
#pragma once
class StaticMath
{
public:
    StaticMath(void);
    ~StaticMath(void);
 
    static double add(double a, double b);//加法
    static double sub(double a, double b);//减法
    static double mul(double a, double b);//乘法
    static double div(double a, double b);//除法

    void print();
};

Under Linux, useartools, and use VS on Windowslib.execompress the object files together, and number and index them for easy lookup and retrieval. The general steps for creating a static library are shown in the figure:

clip_image004[4]

Figure: Process of Creating a Static Library

2.1. Creating and Using Static Libraries on Linux

2.1.1. Linux Static Library Naming Rules

The Linux static library naming convention must be "lib[your_library_name].a": lib is the prefix, the middle is the static library name, and the extension is .a.

2.1.2. Creating a Static Library (.a)

From the above process, we can know that the process of creating a static library on Linux is as follows:

- First, compile the code file into an object file .o (StaticMath.o)

g++ -c StaticMath.cpp

Note: use the -c parameter; otherwise it will be compiled directly into an executable file.

- Then, use the ar tool to package the object file into an .a static library file

ar -crv libstaticmath.a StaticMath.o

Generate the static librarylibstaticmath.a。

clip_image006[4]

For larger projects, makefile files (and project management tools such as CMake) are written to generate static libraries; entering multiple commands is too troublesome.

2.1.3. Using Static Libraries

Write test code that uses the static library created above:

Test code:
#include "StaticMath.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << StaticMath::add(a, b) << endl;
    cout << "a - b = " << StaticMath::sub(a, b) << endl;
    cout << "a * b = " << StaticMath::mul(a, b) << endl;
    cout << "a / b = " << StaticMath::div(a, b) << endl;

    StaticMath sm;
    sm.print();

    system("pause");
    return 0;
}

To use a static library on Linux, you just need to specify the search path of the static library (-L option) and specify the static library name (no lib prefix or .a suffix needed, -l option) at compile time.

# g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath

clip_image008[4]

- -L: Indicates the directory where the library to be linked is located

- -l: Specifies the dynamic library needed for linking. The compiler has an implicit naming rule when looking for dynamic libraries: it adds lib before the given name and .a or .so after it to determine the library name.

2.2. Creating and Using Static Libraries on Windows

2.2.1. Creating a Static Library (.lib)

If you use the VS command line to generate a static library, the program is also generated in two steps:

- First, by using the compiler option/cofCl.execompile the code (cl /c StaticMath.cpp), create an object file named "StaticMath.obj".

- Then, use the library managerLib.exeto link the code (lib StaticMath.obj), create the static library StaticMath.lib.

Of course, we usually don't do it this way; it is more convenient to use VS project settings. When creating a Win32 console application, check the static library type; open the project "Property Pages" -> "Configuration Properties" -> "General", and select Static Library as the Configuration Type.

clip_image010[4]

Figure: VS static library project property settings

Build the project to generate the static library.

2.2.2. Using Static Libraries

The test code is the same as on Linux. There are 3 ways to use it:

Method 1:

How to use a static library in VS:

- In the project "Property Pages" -> "Common Properties" -> "Framework and References" -> "Add Reference", the "Add Reference" dialog box will appear. The "Project" tab lists the projects in the current solution and all libraries that can be referenced. On the "Project" tab, select StaticLibrary. Click "OK".

clip_image012[4]

- Add the StaticMath.h header file directory; you must modify the include directory path. Open the project "Property Pages" -> "Configuration Properties" -> "C/C++" -> "General", and in the "Additional Include Directories" property value, type the path to the directory containing the StaticMath.h header file or browse to that directory.

clip_image014[4]

Compile and run OK.

clip_image015[4]

Figure: Static library test result (VS)

If the referenced static library is not a sub-project under the same solution, but uses a third-party static library lib and header file, the above method cannot be set. There are 2 other methods that are also feasible.

Method 2:

Open the project "Property Pages" -> "Configuration Properties" -> "Linker" -> "Command Line", and enter the full path of the static library.

clip_image017[4]

Method 3:

- "Property Pages" -> "Configuration Properties" -> "Linker" -> "General", enter the directory where the static library is located in Additional Library Directories;

- "Property Pages" -> "Configuration Properties" -> "Linker" -> "Input", enter the static library name StaticLibrary.lib in Additional Dependencies.

clip_image019[4]

3. Dynamic Libraries

From the introduction above, static libraries are easy to use and understand, and also achieve the purpose of code reuse. So why do we still need dynamic libraries?

3.1. Why Are Dynamic Libraries Still Needed?

The need for dynamic libraries is actually caused by the characteristics of static libraries.

- Space waste is one problem with static libraries.

clip_image021[4]

- Another problem is that static libraries bring trouble to program updates, deployment, and release. If the static library liba.lib is updated, all applications using it need to be recompiled and released to users (for users, it may be a very small change, but it causes the entire program to be re-downloaded,full update)。

Dynamic libraries are not linked into the object code at compile time, but are loaded only when the program is running.If different applications call the same library, then only one instance of that shared library is needed in memory., avoiding the problem of space waste. Dynamic libraries are loaded only when the program is running, which also solves the trouble that static libraries bring to program updates, deployment, and release. Users only need to update the dynamic library,incremental update.。

clip_image023[4]

Summary of dynamic library characteristics:

- Dynamic libraries postpone the linking and loading of some library functions to the time when the program runs.

- It can realize resource sharing between processes. (Therefore, dynamic libraries are also called shared libraries.)

- It makes upgrading some programs simple.

- It can even truly achieve that linking and loading are completely controlled by the programmer in the program code (explicit calling)。

Windows and Linux have different executable file formats, so there are some differences when creating dynamic libraries.

Under the Windows system, the executable file format is PE format, and a dynamic library requires aDllMain function serves as the initialization entry point. Typically, when declaring exported functions, you need _declspec(dllexport).keyword。

- Under Linux, executable files compiled by gcc are in ELF format by default.No initialization entry point is required, nor do functions need special declarations.This makes development more convenient.

Unlike creating a static library, no packaging tool (ar, lib.exe) is needed; you can create a dynamic library directly with the compiler.

3.2. Creating and Using Dynamic Libraries on Linux

3.2.1. Naming conventions for Linux dynamic libraries

The name of a dynamic link library takes the form libxxx.so, with the prefix "lib" and the suffix ".so".

- For the actual library file, each shared library has a special name called "soname". After the program starts, it uses this name to tell the dynamic loader which shared library to load.

- In the file system, soname is only a link to the actual dynamic library. For dynamic libraries, each library also has another name for the compiler to use. It is a link file pointing to the actual library image file (lib+soname+.so).

3.2.2. Creating a dynamic library (.so)

Write the dynamic library code for arithmetic operations:

DynamicMath.h header file
#pragma once
class DynamicMath
{
public:
        DynamicMath(void);
        ~DynamicMath(void); 

        static double add(double a, double b);//加法
        static double sub(double a, double b);//减法
        static double mul(double a, double b);//乘法
        static double div(double a, double b);//除法
        void print();
};

- First, generate the object file; at this point, add the compiler option -fpic.

g++ -fPIC -c DynamicMath.cpp

-fPIC creates position-independent code (PIC), so that it can be shared among multiple applications.

- Then, generate the dynamic library; at this point, add the linker option -shared.

g++ -shared -o libdynmath.so DynamicMath.o

-shared specifies the generation of a dynamic link library.

clip_image025[4]

In fact, the above two steps can be combined into one command:

g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp

3.2.3. Using dynamic libraries

Write test code that uses the dynamic library:

Test code:
#include "../DynamicLibrary/DynamicMath.h"

#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << DynamicMath::add(a, b) << endl;
    cout << "a - b = " << DynamicMath::sub(a, b) << endl;
    cout << "a * b = " << DynamicMath::mul(a, b) << endl;
    cout << "a / b = " << DynamicMath::div(a, b) << endl;

    DynamicMath dyn;
    dyn.print();
    return 0;
}

Reference the dynamic library and compile it into an executable file (in the same way as with a static library):

g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath

Then run: ./a.out, and find that it actually reports an error!!!

clip_image027[4]

You might guess that it is because the dynamic library and the test program are not in the same directory. Let us verify whether this is the case:

clip_image029[4]

It still reports an error!!! So, how are shared library files located during execution?

1) When the system loads executable code, it can know the names of the libraries it depends on, but it also needs to know the absolute paths. At this point, the system dynamic linker/loader is needed.

2) For ELF-format executable programs, this is done by ld-linux.so*. It searches the DT_RPATH segment of the ELF file, the environment variable LD_LIBRARY_PATH, the /etc/ld.so.cache file list, and the /lib/ and /usr/lib directories in order, and loads the library file into memory after finding it.

How to make the system able to find it:

- If it is installed under /lib or /usr/lib, then ld can find it by default without any additional operations.

- If it is installed in another directory, you need to add it to the /etc/ld.so.cache file. The steps are as follows:

- Edit the /etc/ld.so.conf file and add the path to the directory containing the library file.

- Run ldconfig; this command will rebuild the /etc/ld.so.cache file.

We copy the created dynamic library to /usr/lib, and then run the test program.

clip_image031[4]

3.3. Creating and Using Dynamic Libraries on Windows

3.3.1. Creating a dynamic library (.dll)

Compared with Linux, creating a dynamic library under the Windows system is a bit more troublesome. First, you need a DllMain function as the initialization entry point (when creating a Win32 console application, selecting the DLL type will automatically generate this file):

dllmain.cpp entry file
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Usually, when declaring exported functions, you need the _declspec(dllexport) keyword:

DynamicMath.h header file
#pragma once
class DynamicMath
{
public:
    __declspec(dllexport) DynamicMath(void);
    __declspec(dllexport) ~DynamicMath(void);

    static __declspec(dllexport) double add(double a, double b);//加法
    static __declspec(dllexport) double sub(double a, double b);//减法
    static __declspec(dllexport) double mul(double a, double b);//乘法
    static __declspec(dllexport) double div(double a, double b);//除法

    __declspec(dllexport) void print();
};

To generate a dynamic library, you need to set the project properties. Open the project "Property Pages" -> "Configuration Properties" -> "General", and select Dynamic Library for Configuration Type.

clip_image033[4]

Figure: v Dynamic library project property settings

Build the project and the dynamic library will be generated.

3.3.2. Using dynamic libraries

Create a Win32 console test program:

TestDynamicLibrary.cpp test program
#include "stdafx.h"
#include "DynamicMath.h"

#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << DynamicMath::add(a, b) << endl;
    cout << "a - b = " << DynamicMath::sub(a, b) << endl;
    cout << "a * b = " << DynamicMath::mul(a, b) << endl;
    cout << "a / b = " << DynamicMath::div(a, b) << endl;

    DynamicMath dyn;
    dyn.print();

    system("pause");
    return 0;
}

Method 1:

- Project "Property Pages" -> "Common Properties" -> "Framework and References" -> "Add Reference"; the "Add Reference" dialog box will be displayed. The "Projects" tab lists the projects in the current solution and all the libraries that can be referenced. In the "Projects" tab, select DynamicLibrary. Click "OK".

clip_image035[4]

- Add the DynamicMath.h header file directory; you must modify the include directory path. Open the project "Property Pages" -> "Configuration Properties" -> "C/C++" -> "General". In the "Additional Include Directories" property value, type or browse to the directory containing the DynamicMath.h header file.

clip_image037[4]

Compile and run OK.

clip_image038[4]

Figure: Dynamic library test results (VS)

Method 2:

- "Property Pages" -> "Configuration Properties" -> "Linker" -> "General"; in Additional Library Directories, enter the directory containing the dynamic library.

clip_image040[4]

- "Property Pages" -> "Configuration Properties" -> "Linker" -> "Input"; in Additional Dependencies, enter DynamicLibrary.lib generated by compiling the dynamic library.

clip_image042[4]

Here you may have a question: why does a dynamic library also have a DynamicLibrary.lib file? That is, whether it is a static link library or a dynamic link library, there is always a lib file in the end. So what is the difference between the two? In fact, they are completely different things.

clip_image044[4]

The size of StaticLibrary.lib is 190KB, and the size of DynamicLibrary.lib is 3KB. The lib file corresponding to a static library is called astatic library, and the lib file corresponding to a dynamic library is called an [import library]. In fact, a static library itself contains the actual executable code, symbol table, etc., whilefor an import library, the actual executable code is located in the dynamic library; the import library only contains the address symbol table and other basic address information to ensure that the program can find the corresponding functions.。

4. Explicitly Calling Dynamic Libraries

The dynamic library usage method introduced above is similar to that of static libraries and belongs to implicit invocation; at compile time, the corresponding library and search path are specified. In fact, dynamic libraries can also be explicitly invoked.[InClanguage], explicitly invoking a dynamic library is a piece of cake!

4.1. Explicitly Calling Dynamic Libraries on Linux

#include <dlfcn.h> provides the following interfaces:

-  void * dlopen(const char *pathname, int mode): The function opens the specified dynamic link library file in the specified mode and returns a handle to the calling process.

-  void* dlsym(void* handle, const char* symbol): dlsym returns the address corresponding to the symbol based on the dynamic link library handle (pHandle) and the symbol. Using this function, you can obtain not only function addresses but also variable addresses.

-  int dlclose(void *handle): dlclose is used to close the dynamic link library with the specified handle. Only when the use count of this dynamic link library reaches 0 will it actually be unloaded by the system.

- const char *dlerror(void): When a dynamic link library operation function fails, dlerror can return error information. A return value of NULL indicates that the operation function was executed successfully.

4.2. Explicitly Calling Dynamic Libraries on Windows

An application must make a function call to explicitly load the DLL at runtime. To explicitly link to a DLL, the application must:

- CallLoadLibrary(or a similar function) to load the DLL and obtain a module handle.

- CallGetProcAddress, to obtain a function pointer to each exported function that the application needs to call. Since the application calls the DLL's functions through pointers, the compiler does not generate external references, so there is no need to link against an import library.

- After using the DLL, callFreeLibrary。

4.3. Points to Note When Explicitly Calling C++ Dynamic Libraries

For C++, the situation is slightly more complicated. The difficulty of explicitly loading a C++ dynamic libraryis partly because ofC++ name mangling;and partly because a suitable one is not providedAPIto load classes, in C++, you may need to use a class in the library, which requires creating an instance of that class, and this is not easy to do.

name manglingThis can be solved with extern "C". C++ has a specific keyword used to declare functions with C binding: extern "C". Functions declared with extern "C" will use the function name as the symbol name, just like C functions. Therefore, only non-member functions can be declared as extern "C", and they cannot be overloaded. Despite many limitations, extern "C" functions are still very useful because they can be dynamically loaded with dlopen just like C functions. Having the extern "C" qualifier does not mean that C++ code cannot be used inside the function. On the contrary, it is still a fully C++ function and can use any C++ features and various types of parameters.

Also, regarding how to obtain classes from C++ dynamic libraries, here are a few related articles, but I do not recommend doing this:

- "LoadLibrary Calling Class in DLL":http://www.cppblog.com/codejie/archive/2009/09/24/97141.html

-  《C++ dlopen mini HOWTO》:http://blog.csdn.net/denny_233/article/details/7255673

"Explicitly" using classes in C++ dynamic libraries is very cumbersome and dangerous, so if implicit use is possible, don't use explicit; if static is possible, don't use dynamic.

5. Appendix: Library-Related Commands on Linux

5.1. g++ (gcc) Compiler Options

- -shared: Specify to generate a dynamic link library.

- -static: Specify to generate a static link library.

- -fPIC: Indicates compiling into position-independent code, used for compiling shared libraries. The object file needs to be created as position-independent code, which conceptually means that when the executable program loads them, they can be placed anywhere in the executable program's memory.

- -L.: Indicates the directory where the library to be linked is located.

- -l: Specify the dynamic library needed at link time. The compiler has an implicit naming rule when looking for dynamic link libraries, that is, adding "lib" before the given name and ".a/.so" after it to determine the library name.

- -Wall: Generate all warning messages.

- -ggdb: This option will generate as much debug information usable by gdb as possible.

- -g: The compiler generates debug information during compilation.

- -c: Only activate preprocessing, compilation, and assembly, that is, turn the program into an object file (.o file).

- -Wl,options: Pass the parameters (options) to the linker ld. If there are commas in options, split options into multiple options and then pass them to the linker program.

5.2. The nm Command

Sometimes you may need to see what functions are in a library.nmcommandIt can print out all symbols involved in the library. The library can be either static or dynamic. There are many symbols listed by nm, and there are three common types:

- One type is called in the library but not defined in the library (indicating that support from other libraries is needed), represented by U;

- One type is functions defined in the library, represented by T, which is the most common;

- One type is the so-called "weak" symbols. Although they are defined in the library, they may be overridden by symbols with the same name in other libraries, represented by W.

$nm libhello.h

5.3. The ldd Command

lddThe command can view the shared libraries that an executable program depends on.For example, the arithmetic dynamic library we wrote depends on the following libraries:

clip_image046[4]

6. Summary

The difference between the two isthe time when code is loaded is different.。

- Static libraries are linked into the object code during program compilation, and the static library will no longer be needed when the program runs.Therefore the size is larger.。

- Dynamic libraries are not linked into the object code during program compilation, but are loaded only when the program runs. Therefore, the dynamic library needs to exist when the program runs.Therefore the code size is smaller.。

The advantage of dynamic libraries is that if different applications call the same library, only one instance of the shared library is needed in memory. While bringing benefits, there are also problems! Such as the classic DLL Hell problem. Regarding how to avoid dynamic library management problems, you can search for relevant materials yourself.

7. Related Tutorials

C++ Tutorial:http://www.w3cschool.cc/cplusplus/cpp-tutorial.html

Author: Wu Qin
Source: http://www.cnblogs.com/skynet/