25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 

26 KiB

Visual Studio 2019 库学习文档

1. 学习目标

本文档用于记录 Visual Studio 2019 平台下库文件的生成与使用方法,主要包括静态库和动态库两部分内容。

完成本文档学习后,应能够完成以下操作:

  1. 理解库文件的作用,以及库文件在工程复用、源码隐藏和多人协作中的意义;
  2. 理解静态库和动态库的基本概念;
  3. 能够在 VS2019 中创建并生成静态库 .lib
  4. 能够在其他工程中通过工程配置方式调用静态库;
  5. 能够在代码中通过语句加载 .lib
  6. 能够在 VS2019 中创建并生成动态库 .dll
  7. 掌握通过导出语句生成动态库的方法;
  8. 掌握通过模块定义文件 .def 生成动态库的方法;
  9. 能够通过工程配置方式调用动态库;
  10. 能够在代码中通过语句加载 .lib 调用动态库;
  11. 能够在代码中通过 LoadLibraryGetProcAddress 加载 .dll 并调用函数;
  12. 能够排查库调用过程中常见的头文件、库路径、平台不一致、运行时找不到 DLL 等问题。

2. 文档目录结构

Library 学习文档按照基础学习任务要求进行存放,推荐目录结构如下:

Library
|---pictures
|   |---Library_001_学习目标.png
|   |---Library_002_目录结构.png
|   |---Library_003_库的作用.png
|   |---Library_004_静态库和动态库关系.png
|   |---Library_005_创建静态库项目.png
|   |---Library_006_静态库项目属性.png
|   |---Library_007_生成静态库.png
|   |---Library_008_调用静态库配置.png
|   |---Library_009_创建动态库项目.png
|   |---Library_010_导出语句生成动态库.png
|   |---Library_011_DEF文件生成动态库.png
|   |---Library_012_动态库调用配置.png
|   |---Library_013_DLL运行目录.png
|   |---Library_014_常见错误.png
|   +---Library_015_验收总结.png
+---Library.md

图片统一放在 pictures 文件夹下,Markdown 文档中通过相对路径进行引用。

3. 库的基本概念

3.1 什么是库

库可以理解为已经写好并封装好的功能模块。库中通常包含一组函数、类或接口,其他工程可以通过包含头文件并链接库文件的方式来使用这些功能。

在 C/C++ 工程中,常见库文件包括:

类型 常见后缀 说明
静态库 .lib 在链接阶段被合并到最终程序中
动态库 .dll 程序运行时加载和使用
动态库导入库 .lib 配合 .dll 使用,保存 DLL 中函数的导入信息
头文件 .h 提供函数声明、类型定义、宏定义等接口信息

需要注意:VS2019 中 .lib 可能有两种含义。第一种是静态库文件,里面包含真正的函数实现;第二种是动态库的导入库,里面不保存完整实现,只保存链接 DLL 所需的导入信息。

3.2 使用库的意义

自建库或调用库的意义主要体现在代码复用、工程结构清晰、隐藏源码和团队协作等方面。

意义 说明
代码复用 一份稳定代码可以被多个工程重复使用
工程清晰 将算法、通信、驱动等模块拆分出来,主工程更清楚
隐藏源码 调用方只看到 .h.lib/.dll,看不到内部实现源码
方便协作 不同人员负责不同库,通过接口进行协作
降低耦合 主程序只依赖接口,不直接关心库内部实现
提高编译效率 稳定模块可提前编译成库,减少主工程重复编译

例如在嵌入式软件项目中,常见的库包括:

MotorControl.lib
Modbus.lib
CanProtocol.lib
FilterAlgo.lib
DriverLib.lib

主程序只需要调用库提供的接口,例如:

Motor_Start();
Motor_SetSpeed(1000);
Modbus_Poll();

而不需要关心库内部如何实现。

3.3 静态库和动态库的区别

静态库和动态库都可以实现代码复用,但它们参与程序的时机不同。

对比项 静态库 动态库
常见文件 .lib .dll + .lib
使用时机 链接阶段合并到程序中 程序运行时加载 DLL
生成结果 最终 .exe 中包含库代码 .exe 运行时依赖 .dll
发布文件 通常只需要 .exe 需要 .exe.dll 一起发布
更新方式 修改库后需要重新链接程序 替换 DLL 后可能不需要重新编译主程序
源码隐藏 可以隐藏源码 可以隐藏源码
运行依赖 不依赖单独 DLL 运行时必须能找到 DLL

简单理解:

静态库:编译链接时放进 exe 里面。
动态库:运行时由 exe 去加载 dll。

3.4 头文件、库文件、可执行文件的关系

调用库时通常需要理解三个文件的作用:

文件 作用
.h 告诉编译器有哪些函数可以调用
.lib 告诉链接器函数实现在哪里,或者如何导入 DLL 中的函数
.dll 动态库真正运行时被加载的文件
.exe 最终运行的主程序

以调用一个数学库为例:

MathLib.h      提供函数声明
MathLib.lib    提供静态库实现,或者提供 DLL 导入信息
MathDll.dll    动态库真正运行文件
MainApp.exe    调用库的主程序

编译、链接、运行的关系如下:

编译阶段:检查头文件和函数声明
链接阶段:检查 .lib 和函数实现
运行阶段:如果使用 DLL,需要能找到 .dll 文件

4. 静态库

4.1 静态库的基本概念

静态库是在链接阶段被合并进最终程序的库文件。在 VS2019 中,静态库文件通常以 .lib 为后缀。

静态库本身不能直接运行,因为它不是完整程序,没有 main 函数。它的作用是把一部分功能代码编译成库,供其他应用程序工程调用。

例如:

MathLib.lib

可以提供如下函数:

int Add(int a, int b);
int Sub(int a, int b);

主程序工程通过包含头文件并链接 MathLib.lib 后,就可以调用 AddSub 函数。

4.2 静态库的生成

4.2.1 创建静态库项目

操作步骤:

  1. 打开 Visual Studio 2019

  2. 点击 创建新项目

  3. 搜索并选择 空项目

  4. 输入项目名称,例如:

    MathLib
    
  5. 创建项目后,右键项目,选择 属性

  6. 进入:

    配置属性 -> 常规 -> 配置类型
    
  7. 将配置类型设置为:

    静态库(.lib)
    
  8. 点击 应用,然后点击 确定

创建静态库项目

4.2.2 编写静态库头文件

在静态库项目中添加头文件 MathLib.h

#ifndef MATH_LIB_H
#define MATH_LIB_H

int Add(int a, int b);
int Sub(int a, int b);

#endif

头文件的作用是向调用方提供函数声明。调用方包含该头文件后,编译器才能知道 AddSub 函数的参数和返回值。

静态库头文件

4.2.3 编写静态库源文件

在静态库项目中添加源文件 MathLib.cpp

#include "MathLib.h"

int Add(int a, int b)
{
    return a + b;
}

int Sub(int a, int b)
{
    return a - b;
}

源文件中保存函数的真正实现。生成静态库时,这些函数实现会被编译进 .lib 文件中。

静态库源文件

4.2.4 生成静态库文件

生成步骤:

  1. 在顶部选择正确配置,例如 DebugRelease

  2. 选择正确平台,例如 Win32x64

  3. 点击菜单:

    生成 -> 生成解决方案
    
  4. 或使用快捷键:

    Ctrl + Shift + B
    
  5. 生成成功后,可以在输出目录中找到:

    MathLib.lib
    

默认情况下,常见输出目录可能类似:

项目目录\Debug\MathLib.lib
项目目录\x64\Debug\MathLib.lib

具体路径以项目属性中的输出目录为准。

生成静态库

4.3 静态库的调用

静态库调用方通常是一个应用程序项目,例如 MainApp.exe。调用静态库需要完成三件事:

包含头文件
配置库文件路径
配置库文件名称

静态库调用流程

4.3.1 在工程配置中调用静态库

假设静态库文件结构如下:

LibraryDemo
|---MathLib
|   |---MathLib.h
|   +---MathLib.lib
|
+---MainApp
    +---main.cpp

调用方工程需要完成以下配置。

第一步,配置头文件路径:

项目属性 -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录

添加 MathLib.h 所在目录,例如:

$(SolutionDir)MathLib

第二步,配置库文件路径:

项目属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录

添加 MathLib.lib 所在目录,例如:

$(SolutionDir)MathLib\$(Platform)\$(Configuration)

工程配置调用静态库

第三步,配置库文件名称:

项目属性 -> 配置属性 -> 链接器 -> 输入 -> 附加依赖项

添加:

MathLib.lib

工程配置调用静态库

4.3.2 在代码中调用静态库函数

主程序 main.cpp 示例:

#include <stdio.h>
#include "MathLib.h"

int main(void)
{
    int ret1 = Add(1, 2);
    int ret2 = Sub(5, 3);

    printf("ret1 = %d\n", ret1);
    printf("ret2 = %d\n", ret2);

    return 0;
}

运行结果应为:

ret1 = 3
ret2 = 2

代码调用静态库

4.3.3 在代码中使用语句加载 lib 调用

除了在工程属性中填写 附加依赖项,也可以在代码中使用 #pragma comment(lib, "xxx.lib") 指定需要链接的库文件。

示例:

#include <stdio.h>
#include "MathLib.h"

#pragma comment(lib, "MathLib.lib")

int main(void)
{
    int ret = Add(1, 2);
    printf("ret = %d\n", ret);
    return 0;
}

需要注意:#pragma comment(lib, "MathLib.lib") 只指定库文件名,库文件所在目录仍然需要通过 附加库目录 配置,或者将 .lib 放到链接器可以搜索到的位置。

也就是说,即使使用代码语句加载 .lib,通常仍然需要配置:

项目属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录

4.4 静态库调用注意事项

静态库调用时需要重点注意以下几点:

  1. 主程序和静态库的平台必须一致,例如都为 Win32 或都为 x64
  2. 主程序和静态库的运行库配置建议保持一致,例如都使用 /MDd 或都使用 /MD
  3. 头文件路径配置的是目录,不是具体 .h 文件;
  4. 附加库目录配置的是 .lib 所在文件夹,不是 .lib 文件本身;
  5. 附加依赖项中填写的是具体 .lib 文件名;
  6. 如果函数只有声明没有实现,会出现无法解析外部符号;
  7. 如果 .cpp 没有加入静态库项目,也可能导致函数无法解析。

常见错误对应关系如下:

问题 优先检查内容
找不到头文件 附加包含目录
找不到 .lib 附加库目录、附加依赖项
函数无法解析 函数实现、源文件是否加入项目、库是否链接
x64 正常但 Win32 异常 平台配置是否一致
Debug 正常但 Release 异常 Debug/Release 属性是否都配置

5. 动态库

5.1 动态库的基本概念

动态库是在程序运行时被加载的库文件。在 Windows 平台下,动态库文件通常以 .dll 为后缀。

在 VS2019 中生成动态库时,通常会生成两个重要文件:

MathDll.dll
MathDll.lib

其中:

文件 作用
.dll 动态库运行时真正被加载的文件,保存函数实现
.lib 动态库导入库,提供链接阶段所需的导入信息

需要注意:动态库项目生成的 .lib 通常不是静态库,它只是导入库。真正运行时仍然需要 .dll 文件存在。

简单理解:

静态库的 .lib:保存真正实现,链接进 exe。
动态库的 .lib:保存导入信息,运行时还要找 dll。

5.2 动态库的生成

动态库生成方式主要有两种:

  1. 通过导出语句生成;
  2. 通过模块定义文件 .def 生成。

5.3 通过导出语句生成动态库

5.3.1 创建动态库项目

操作步骤:

  1. 打开 Visual Studio 2019

  2. 创建一个空项目,例如:

    MathDll
    
  3. 右键项目,选择 属性

  4. 进入:

    配置属性 -> 常规 -> 配置类型
    
  5. 将配置类型设置为:

    动态库(.dll)
    
  6. 点击 应用,然后点击 确定

创建动态库项目

5.3.2 编写导出宏

添加头文件 MathDll.h

#ifndef MATH_DLL_H
#define MATH_DLL_H

#ifdef MATHDLL_EXPORTS
#define MATHDLL_API __declspec(dllexport)
#else
#define MATHDLL_API __declspec(dllimport)
#endif

extern "C" MATHDLL_API int Add(int a, int b);
extern "C" MATHDLL_API int Sub(int a, int b);

#endif

说明:

内容 说明
__declspec(dllexport) 生成 DLL 时导出函数
__declspec(dllimport) 调用 DLL 时导入函数
extern "C" 防止 C++ 函数名修饰,方便按函数名查找
MATHDLL_EXPORTS 用于区分当前是生成 DLL 还是调用 DLL

在 DLL 项目中需要定义宏:

MATHDLL_EXPORTS

通常配置位置为:

项目属性 -> 配置属性 -> C/C++ -> 预处理器 -> 预处理器定义

动态库导出宏

5.3.3 编写动态库源文件

添加源文件 MathDll.cpp

#include "MathDll.h"

int Add(int a, int b)
{
    return a + b;
}

int Sub(int a, int b)
{
    return a - b;
}

生成动态库后,AddSub 函数会被导出,其他程序可以调用它们。

动态库源文件

5.3.4 生成动态库文件

点击:

生成 -> 生成解决方案

或使用快捷键:

Ctrl + Shift + B

生成成功后,通常可以得到:

MathDll.dll
MathDll.lib

其中 .dll 是运行时文件,.lib 是导入库。

动态库源文件

5.4 通过模块定义文件生成动态库

模块定义文件通常以 .def 为后缀,用于明确指定动态库导出的函数名称。

5.4.1 编写 DLL 头文件

MathDllDef.h 示例:

#ifndef MATH_DLL_DEF_H
#define MATH_DLL_DEF_H

extern "C" int Add(int a, int b);
extern "C" int Sub(int a, int b);

#endif

这里不使用 __declspec(dllexport),而是通过 .def 文件指定导出函数。

DEF头文件

5.4.2 编写 DLL 源文件

MathDllDef.cpp 示例:

#include "MathDllDef.h"

int Add(int a, int b)
{
    return a + b;
}

int Sub(int a, int b)
{
    return a - b;
}

DEF源文件

5.4.3 添加模块定义文件

添加文件 MathDllDef.def

LIBRARY "MathDllDef"

EXPORTS
    Add
    Sub

.def 文件中:

关键字 说明
LIBRARY 指定生成的 DLL 名称
EXPORTS 指定需要导出的函数列表

然后在项目属性中配置模块定义文件:

项目属性 -> 配置属性 -> 链接器 -> 输入 -> 模块定义文件

填写:

MathDllDef.def

模块定义文件配置

5.4.4 DEF 文件方式注意事项

使用 .def 文件导出函数时需要注意:

  1. .def 文件中的函数名必须和实际函数名对应;
  2. C++ 函数可能存在函数名修饰,建议配合 extern "C" 使用;
  3. .def 文件适合集中管理导出函数;
  4. 如果导出函数较多,.def 文件比在每个函数前写导出语句更清晰。

DEF注意事项

5.5 动态库的调用

动态库的调用方式主要有三种:

  1. 在工程配置中调用;
  2. 在代码中使用语句加载 .lib 调用;
  3. 在代码中使用语句加载 .dll 调用。

动态库调用方式

5.6 在工程配置中调用动态库

这种方式也叫隐式链接。调用方在编译链接阶段链接动态库生成的 .lib 导入库,程序运行时再加载 .dll

调用方需要完成三件事:

包含头文件
配置导入库 .lib 路径
配置导入库 .lib 名称

第一步,配置头文件路径:

项目属性 -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录

第二步,配置 .lib 所在目录:

项目属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录

第三步,配置 .lib 文件名:

项目属性 -> 配置属性 -> 链接器 -> 输入 -> 附加依赖项

例如:

MathDll.lib

第四步,保证运行时能找到 .dll 文件。常见做法是将 DLL 放到:

主程序 exe 同级目录

主程序示例:

#include <stdio.h>
#include "MathDll.h"

int main(void)
{
    int ret = Add(1, 2);
    printf("ret = %d\n", ret);
    return 0;
}

工程配置调用动态库

5.7 在代码中语句加载 lib 调用动态库

调用动态库时,也可以在代码中使用 #pragma comment(lib, "xxx.lib") 指定导入库。

示例:

#include <stdio.h>
#include "MathDll.h"

#pragma comment(lib, "MathDll.lib")

int main(void)
{
    int ret = Add(1, 2);
    printf("ret = %d\n", ret);
    return 0;
}

需要注意:

  1. 这里加载的是动态库的导入库 .lib
  2. 运行时仍然需要 MathDll.dll
  3. .dll 一般需要放到 .exe 同级目录;
  4. 如果找不到 DLL,程序运行时会报错,而不是编译时报错。

代码加载lib调用动态库

5.8 在代码中语句加载 dll 调用动态库

这种方式也叫显式加载,程序运行过程中主动调用 Windows API 加载 DLL。

常用函数包括:

函数 说明
LoadLibrary 加载 DLL
GetProcAddress 获取 DLL 中导出函数地址
FreeLibrary 释放 DLL

示例代码:

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

typedef int (*PFN_ADD)(int, int);

int main(void)
{
    HMODULE hDll = LoadLibraryA("MathDll.dll");
    if (hDll == NULL)
    {
        printf("LoadLibrary failed\n");
        return -1;
    }

    PFN_ADD pAdd = (PFN_ADD)GetProcAddress(hDll, "Add");
    if (pAdd == NULL)
    {
        printf("GetProcAddress failed\n");
        FreeLibrary(hDll);
        return -1;
    }

    int ret = pAdd(1, 2);
    printf("ret = %d\n", ret);

    FreeLibrary(hDll);
    return 0;
}

这种方式不需要在链接器中配置 MathDll.lib,但必须保证运行时能找到 MathDll.dll,并且函数名和导出名一致。

5.9 动态库调用注意事项

动态库调用时需要注意以下几点:

  1. 使用工程配置方式调用 DLL 时,需要 .h.lib.dll
  2. .lib 用于链接阶段,.dll 用于运行阶段;
  3. DLL 找不到通常是运行时错误;
  4. 主程序和 DLL 的平台必须一致;
  5. 函数导出名必须正确;
  6. C++ 函数建议使用 extern "C" 避免函数名被修饰;
  7. DLL 可以放在 exe 同级目录,也可以放在系统 PATH 能找到的目录;
  8. 显式加载 DLL 时,要检查 LoadLibraryGetProcAddress 的返回值。

动态库调用注意事项

6. 静态库和动态库对比总结

静态库和动态库都是代码复用的重要方式,但使用场景不同。

对比项 静态库 动态库
主要文件 .lib .dll.lib
是否可直接运行 不可以 不可以
是否需要主程序 需要 需要
链接方式 链接阶段合入程序 链接导入库,运行时加载 DLL
运行依赖 通常不依赖额外 DLL 必须能找到 DLL
更新方式 更新库后通常要重新链接主程序 可通过替换 DLL 更新实现
适合场景 稳定模块、简单发布 插件、模块更新、运行时加载

简单选择原则:

想让程序发布简单,可以优先考虑静态库。
想让模块可以单独更新,可以考虑动态库。
想运行时决定是否加载某个模块,可以使用 LoadLibrary 显式加载 DLL。

7. 常见问题和排查方法

7.1 找不到头文件

常见报错:

无法打开包括文件: “xxx.h”: No such file or directory

原因通常是 附加包含目录 没有配置,或者 #include 路径写错。

优先检查:

项目属性 -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录

7.2 找不到 lib 文件

常见报错:

LINK : fatal error LNK1104: 无法打开文件 “xxx.lib”

原因通常是 .lib 文件路径错误,或者附加依赖项中库文件名写错。

优先检查:

项目属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录
项目属性 -> 配置属性 -> 链接器 -> 输入 -> 附加依赖项

7.3 无法解析的外部符号

常见报错:

error LNK2019: 无法解析的外部符号

可能原因:

  1. 函数只有声明,没有实现;
  2. 实现函数的源文件没有加入项目;
  3. 没有链接正确的库文件;
  4. C/C++ 混合调用时函数名不一致;
  5. 平台或配置不一致。

7.4 运行时找不到 DLL

常见现象:程序编译和链接成功,但运行时提示找不到 DLL。

可能原因:

  1. DLL 没有放到 exe 同级目录;
  2. DLL 不在系统 PATH 路径中;
  3. Debug/Release 使用了不同输出路径;
  4. Win32/x64 平台 DLL 放错;
  5. DLL 文件名和程序依赖名不一致。

常见解决方法:

将 DLL 放到 exe 所在目录。

7.5 平台不一致

如果主程序是 x64,而库文件是 Win32,通常会出现链接错误或运行异常。

排查时需要确认:

主程序平台 = 库文件平台 = DLL 平台

例如都使用:

x64 Debug

或者都使用:

Win32 Debug

8. 学习练习

8.1 练习一:生成静态库并调用

练习目标:掌握静态库的生成和工程配置调用方法。

要求:

  1. 创建静态库项目 MathLib
  2. 添加 MathLib.hMathLib.cpp
  3. 实现 AddSub 函数;
  4. 生成 MathLib.lib
  5. 创建主程序项目 MainApp
  6. 在主程序中配置头文件路径、库文件路径和库文件名称;
  7. 调用 Add 函数并输出结果。

8.2 练习二:通过 pragma 调用静态库

练习目标:掌握通过代码语句指定 .lib 的方法。

要求:

  1. 在主程序中包含静态库头文件;

  2. 使用:

    #pragma comment(lib, "MathLib.lib")
    
  3. 配置附加库目录;

  4. 调用库函数并运行程序。

8.3 练习三:通过导出语句生成动态库并调用

练习目标:掌握 __declspec(dllexport)__declspec(dllimport) 的使用。

要求:

  1. 创建动态库项目 MathDll
  2. 编写导出宏;
  3. 导出 Add 函数;
  4. 生成 MathDll.dllMathDll.lib
  5. 创建主程序项目;
  6. 配置头文件路径、导入库路径和导入库名称;
  7. 将 DLL 放到 exe 同级目录;
  8. 调用 Add 函数并运行。

8.4 练习四:通过 DEF 文件生成动态库并调用

练习目标:掌握 .def 文件导出函数的方法。

要求:

  1. 创建动态库项目;
  2. 添加 .def 文件;
  3. .def 文件中写入 EXPORTS
  4. 配置模块定义文件;
  5. 生成 DLL;
  6. 在主程序中调用 DLL 导出的函数。

8.5 练习五:使用 LoadLibrary 加载 DLL

练习目标:掌握运行时显式加载 DLL 的方法。

要求:

  1. 准备一个已经生成的 DLL;
  2. 在主程序中调用 LoadLibraryA
  3. 使用 GetProcAddress 获取函数地址;
  4. 通过函数指针调用 DLL 函数;
  5. 使用 FreeLibrary 释放 DLL。

9. 验收重点总结

Library 部分验收时,应重点掌握以下内容:

分类 必须掌握内容
静态库概念 理解静态库 .lib 的作用
静态库生成 能够创建静态库项目并生成 .lib
静态库调用 能够通过工程配置调用静态库
代码加载 lib 能够使用 #pragma comment(lib, "xxx.lib")
动态库概念 理解 .dll 和导入库 .lib 的关系
导出语句 能够使用 __declspec(dllexport) 导出函数
模块定义文件 能够使用 .def 文件导出函数
动态库工程配置调用 能够配置头文件路径、导入库路径和导入库名称
代码加载 DLL 能够使用 LoadLibraryGetProcAddress 调用 DLL
错误排查 能够排查找不到头文件、找不到 lib、找不到 DLL、平台不一致等问题

10. 学习结论

通过本次学习,掌握了 VS2019 平台下静态库和动态库的基本概念、生成方法和调用方法。

静态库适合将稳定代码直接链接进主程序,发布简单,运行时不需要额外 DLL。动态库适合需要运行时加载、模块独立更新或隐藏实现的场景,但发布时需要保证 DLL 能被程序找到。

在实际使用中,需要重点理解以下关系:

.h 文件:提供接口声明
.lib 文件:静态库实现,或动态库导入信息
.dll 文件:动态库运行时真正加载的实现
.exe 文件:调用库的主程序

库调用问题排查时,应按照以下顺序分析:

编译阶段找不到 .h -> 检查附加包含目录
链接阶段找不到 .lib -> 检查附加库目录和附加依赖项
链接阶段函数无法解析 -> 检查函数实现和库是否正确链接
运行阶段找不到 .dll -> 检查 DLL 是否在 exe 同级目录或 PATH 中
平台相关错误 -> 检查 Win32/x64 是否一致

掌握库的生成与使用后,可以更好地理解公司项目中模块封装、源码隐藏、库文件发布和多人协作的基本方式。