C ++ static and dynamic library on Windows as well as create, use

First, what is the library

Library is an existing, mature, you can reuse code written. In reality every program depends on many underlying foundation of the library, not every person's code from scratch, so there is unusual significance library.

Essentially library is a form of executable binary code, the operating system can be loaded into memory to perform. The library has two types: static libraries (.a or .lib) and dynamic libraries (.so or .dll).

The so-called static, dynamic refers to the link. Recall that a program is compiled into an executable program steps:

img


Second, what is a static library

[] Have become static library, because the link stage, will be compiled .o object files generated with reference to the library packed with links to the executable file. Therefore, the corresponding link is called static linking.

Imagine static library and link the resulting object files compiled together into an executable file, the static library must be similar with the .o file format. In fact, a static library can be viewed as a set of simple collection of object files (.o / .obj files), a file that is a lot of target files after compression packaged form. Static library features summary:

  • Static library for linked library is on the compile-time completion.
  • Program at run-time libraries with no connection to facilitate the transplant.
  • Waste of space and resources, because all object files and libraries involved are linked into one executable file.

Write the following simple four arithmetic C ++ classes, which will be compiled into a static library to others with the header file as follows:

#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();
};

Include pragma oncefile statements will only be compiled once, and with headers #ifndef... #define... #endifeffect is similar.


Third, create and use a static library under Windows

3.1 Creating Static Libraries

If you are using VS command line to generate static libraries, but also in two steps to generate the program:

  • First, by using the compiler option with a / c of Cl.exe compiled code (cl / c StaticMath.cpp), create the target file named "StaticMath.obj" of.
  • Then, use the library manager Lib.exe link code (lib StaticMath.obj), create a static library StaticMath.lib.

Of course, we generally do not use this, use the VS project setting more convenient. When you create a Win32 console application, check the static library types; open the project "Property Panel" → "Configuration Properties" → "General", choose the configuration type static library.

img


Compile the project to generate static library.


3.2 static library

Create a Win32 console test program:

#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;
}


There are three kinds of use:

method one:

This is the most commonly used method:

  • "Properties panel" → "Configuration Properties" → "Linker" → "General" directory input additional dependencies, static library directory;
  • "Property Panel" → "Configuration Properties" → "linker" → "enter", additional static library dependencies enter the name of StaticLibrary.lib.

img


Compile and run OK.

img


Method Two:

Open the project "Property Panel" → "Configuration Properties" → "linker" → "command line", you can enter the full path of the static library.

img


Method three:

Project "Property Panel" → "General Properties" → "framework and reference" → "Add Reference", the "Add Reference" dialog box. "Project" tab lists the current solution for each project as well as all libraries that can be referenced. In the "Project" tab, select StaticLibrary, click "OK."

img


Add StaticMath.h header file directory, you must modify the directory that contains the path. Open the project "Property Panel" → "Configuration Properties" → "C / C ++" → "General", the attribute value "Additional Include Directories", type the path StaticMath.h header file directory or browse to the directory.

img


Fourth, what is the dynamic library

Through the above description found that static library, easy to use and understand, but also to achieve the purpose of code reuse, then why do you need a dynamic library it?

Why do we need a dynamic library, static library is in fact characteristic of lead.

  • Waste of space is an issue static library.

    img

  • Another problem is static database updates to the program, deploy and publish pages will bring trouble. If the static library liba.lib updated, so the use of its applications need to be recompiled, issued to the user (for the players, it may be a small change, but it leads to re-download the entire program, the total amount of update).

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。

img


动态库特点总结:

  • 动态库把对一些库函数的链接载入推迟到程序运行的时期。
  • 可以实现进程之间的资源共享。(因此动态库也称为共享库)
  • 将一些程序升级变得简单。
  • 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。

Window 与 Linux 执行文件格式不同,在创建动态库的时候有一些差异。

  • 在 Windows 系统下的执行文件格式是 PE 格式,动态库需要一个 DllMain 函数做出初始化的入口,通常在导出函数的声明时需要有 _declspec(dllexport)关 键字。
  • Linux 下 gcc 编译的执行文件默认是 ELF 格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。


五、Windows 下创建与使用动态库

5.1 创建动态库

与 Linux 相比,在 Windows 系统下创建动态库要稍微麻烦一些。首先,需要一个 DllMain 函数做出初始化的入口(创建 win32 控制台程序时,勾选 DLL 类型会自动生成这个文件):

// 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;
}

通常在导出函数的声明时需要有 _declspec(dllexport) 关键字:

#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();
};

生成动态库需要设置工程属性,打开工程 “属性面板” → ”配置属性” → ”常规”,配置类型选择动态库。

img

编译项目即可生成动态库。


5.2 使用动态库

创建 Win32 控制台测试程序:

#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;
}


有 2 种使用方法:

方法一:

“属性面板” → ”配置属性” → “链接器” → ”常规”,附加依赖库目录中输入,动态库所在目录;

img


“属性面板” → ”配置属性” → “链接器” → ”输入”,附加依赖库中输入动态库编译出来的 DynamicLibrary.lib。

img


编译运行 OK。

img


这里可能大家有个疑问,动态库怎么还有一个 DynamicLibrary.lib 文件?即无论是静态链接库还是动态链接库,最后都有 lib 文件,那么两者区别是什么呢?其实,两个是完全不一样的东西。

img

StaticLibrary.lib 的大小为 190KB,DynamicLibrary.lib 的大小为 3KB,静态库对应的 lib 文件叫静态库,动态库对应的lib文件叫【导入库】。实际上静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。


方法二:

  • 工程 “属性面板” → “通用属性” → “框架和引用” → ”添加引用”,将显示 “添加引用” 对话框。“项目” 选项卡列出了当前解决方案中的各个项目以及可以引用的所有库。 在 “项目” 选项卡中,选择 DynamicLibrary,单击 “确定”。

    img


  • 添加 DynamicMath.h 头文件目录,必须修改包含目录路径。打开工程 “属性面板” → ”配置属性” → “C/C++” → ” 常规”,在 “附加包含目录” 属性值中,键入 DynamicMath.h 头文件所在目录的路径或浏览至该目录。

    img


六、在 Windows 下显式调用动态库

应用程序必须进行函数调用以在运行时显式加载 DLL。为显式链接到 DLL,应用程序必须:

  • 调用 LoadLibrary(或相似的函数)以加载 DLL 和获取模块句柄。
  • 调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。由于应用程序是通过指针调用 DLL 的函数,编译器不生成外部引用,故无需与导入库链接。
  • 使用完 DLL 后调用 FreeLibrary。

对 C++ 来说,情况稍微复杂。显式加载一个 C++ 动态库的困难一部分是因为 C++ 的 name mangling;另一部分是因为没有提供一个合适的 API 来装载类,在 C++ 中,您可能要用到库中的一个类,而这需要创建该类的一个实例,这不容易做到。

name mangling 可以通过 extern “C” 解决。C++ 有个特定的关键字用来声明采用 C binding 的函数:extern “C” 。用 extern “C” 声明的函数将使用函数名作符号名,就像 C 函数一样。因此,只有非成员函数才能被声明为 extern “C”,并且不能被重载。尽管限制多多,extern “C” 函数还是非常有用,因为它们可以象 C 函数一样被 dlopen 动态加载。冠以 extern “C” 限定符后,并不意味着函数中无法使用 C++ 代码了,相反,它仍然是一个完全的 C++ 函数,可以使用任何 C++ 特性和各种类型的参数。

另外如何从 C++ 动态库中获取类,附上几篇相关文章,但我并不建议这么做:

“显式” 使用 C++ 动态库中的 Class 是非常繁琐和危险的事情,因此能用 “隐式” 就不要用 “显式”,能静态就不要用动态。


七、总结

二者的不同点在于代码被载入的时刻不同。

  • 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库,因此体积较大。
  • 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在,因此代码体积较小。


Static compiler: the compiler to compile an executable file, the executable file will need to call the corresponding static library (.a or .lib) of section extracted, linked into the executable file in order to enable the executable file to run the time does not depend on the dynamic link library.

Dynamic compilation: executable files need comes with a dynamic link library (.so or .dll), when executed, call the corresponding dynamic link library command.

  • Pros: one is reducing the size of the executable file itself, the other is to speed up the compilation speed, saving system resources.
  • Cons: First, even if it is a very simple procedure, just use the link library in a two commands, also comes with a need for relatively large libraries; and second, if there is no corresponding runtime installed on another computer, then use dynamic compilation the executable file will not run.


Being introduced here only to create and use the library under Windows, Linux involves temporarily, after free and then summed up.


reference:

[C / C ++ development] C ++ static and dynamic library and create on Linux and Windows


Guess you like

Origin www.cnblogs.com/linuxAndMcu/p/12057383.html