大众点评爬虫架构深度解析:动态字体加密破解与高可用数据采集方案
2026/5/8 12:06:31
在 Windows 平台开发中,DLL(Dynamic Link Library,动态链接库)是非常核心的一种代码复用方式。
无论是:
都会不可避免地用到C / C++ 调用 DLL。
本文将从零基础视角出发,系统讲清楚:
DLL 是一个“在运行时被加载的函数集合”
和静态库(.lib)的核心区别:
| 项目 | DLL | 静态库 |
|---|---|---|
| 链接时间 | 运行时 | 编译期 |
| 文件 | .dll + .lib | .lib |
| 更新 | 可单独替换 | 需重新编译 |
| 内存 | 多进程共享 | 各自一份 |
// mydll.h#pragmaonce#ifdefMYDLL_EXPORTS#defineMYDLL_API__declspec(dllexport)#else#defineMYDLL_API__declspec(dllimport)#endifextern"C"MYDLL_APIintAdd(inta,intb);// mydll.cpp#defineMYDLL_EXPORTS#include"mydll.h"intAdd(inta,intb){returna+b;}关键点解释:
__declspec(dllexport):导出函数__declspec(dllimport):导入函数extern "C":防止 C++ 名字修饰(非常重要)打开 VS 开发者命令行,在开始菜单中找到并打开:
x64 Native Tools Command PromptforVS2022注意位数:
使用cl.exe生成Debug版DLL(带 PDB)
cl /LD /Zi /Od /MDd /EHsc mydll.cpp各参数含义,编译选项参数说明
| 参数 | 含义 |
|---|---|
| /LD | 生成 DLL |
| /Zi | 生成调试信息(PDB) |
| /Od | 关闭优化(便于调试) |
| /MDd | 使用 Debug CRT(msvcrtd.dll) |
| /EHsc | 标准 C++ 异常处理(推荐) |
D:\test\dll>cl /LD /Zi /Od /MDd /EHsc mydll.cpp 用于 x86 的 Microsoft(R)C/C++ 优化编译器19.50.35720 版 版权所有(C)Microsoft Corporation。保留所有权利。 mydll.cpp Microsoft(R)Incremental Linker Version14.50.35720.0 Copyright(C)Microsoft Corporation. All rights reserved. /out:mydll.dll /dll /implib:mydll.lib /debug mydll.obj D:\test\dll>编译结果
mydll.dll ← Debug DLL
mydll.lib ← 导入库
mydll.pdb ← 调试符号文件(关键)
cl /LD /Zi /Od /MDd mydll.cpp ^ /Fe:Debug\mydll.dll ^ /Fd:Debug\mydll.pdb生成结果:
Debug\├── mydll.dll ├── mydll.lib └── mydll.pdbcl /LD /O2 /MD mydll.cpp| Debug | Release |
|---|---|
| /Zi /Od /MDd | /O2 /MD |
| 有 pdb | 可选 pdb |
| 可单步 | 优化后难调试 |
编译选项参数说明
最终你会得到:
mydll.dll mydll.lib#include<iostream>#include"mydll.h"intmain(){intr=Add(2,3);std::cout<<"result = "<<r<<std::endl;return0;}mydll.libmydll.dll放在:
#include<windows.h>#include<iostream>typedefint(*AddFunc)(int,int);intmain(){HMODULE hDll=LoadLibraryA("mydll.dll");if(!hDll){std::cout<<"LoadLibrary failed"<<std::endl;return-1;}AddFunc Add=(AddFunc)GetProcAddress(hDll,"Add");if(!Add){std::cout<<"GetProcAddress failed"<<std::endl;FreeLibrary(hDll);return-1;}intr=Add(3,4);std::cout<<"result = "<<r<<std::endl;FreeLibrary(hDll);return0;}函数名必须是导出名
extern "C",名字会被修饰函数指针签名必须完全一致,可以使用下面的命令查看函数指针签名
dumpbin /exports mydll.dll__cdecl / __stdcall)这是方式一和方式二的混合体:
.libLoadLibrary判断是否可用适合大型工程 / 插件化 SDK。
class__declspec(dllexport)MyClass{public:intAdd(inta,intb);};工程实践建议:
DLL 对外只暴露 C 接口,内部再用 C++
extern"C"__declspec(dllexport)intFunc();否则GetProcAddress很容易失败。
LoadLibrary失败用dumpbin /headers xxx.dll查看位数
__stdcall vs __cdecl不一致 → 栈损坏 → 程序随机崩溃
Windows 查找 DLL 顺序:
dumpbin /exports mydll.dll可以看到:
这是调试GetProcAddress的神器。
DLL 是 Windows 下模块化的核心能力,
会用 DLL,才算真正进入 C/C++ 工程开发。