动态链接是链接发生在运行时,静态链接是发生在编译时
静态链接存在更多的优化空间,因为编译器和链接器可以从静态链接中看到更多内容,尤其是链接器
动态链接发生在运行时,意味着只有真正启动可执行文件才会加载动态链接库,它实际上并不是可执行文件的一部分
当启动可执行文件时,可执行文件会被加载到内存中,采用动态链接时,会将动态链接库也加载到内存中,
明确程序所需的库,进行动态链接
动态链接更像是“静态链接”了动态库,通过链接静态 lib 文件,知晓函数指针与动态库的对应关系,然后在运行时去调用动态库中的内容
因此相较于静态库设置只需要将 glfw3.lib 换成 glfw3dll.lib,并且将其对应的 glfw3.dll 与可执行文件放在同一个路径下,否则会出现 dll 缺失的错误
/* GLFWAPI is used to declare public API functions for export
* from the DLL / shared library / dynamic library.
*/
#if defined(_WIN32) && defined(_GLFW_BUILD_DLL)
/* We are building GLFW as a Win32 DLL */
#define GLFWAPI __declspec(dllexport)
#elif defined(_WIN32) && defined(GLFW_DLL)
/* We are calling a GLFW Win32 DLL */
#define GLFWAPI __declspec(dllimport)
#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)
/* We are building GLFW as a Unix shared library */
#define GLFWAPI __attribute__((visibility("default")))
#else
#define GLFWAPI
#endif当我们预定义 #define GLFW_DLL 时,上述代码会执行 #define GLFWAPI 语句,即不使用 __declspec(dllimport),但是所写的代码仍然可以运行
在使用 lib+dll 时,比较是否使用 __declspec(dllimport) 的区别
使用 __declspec(dllimport) | 不使用 __declspec(dllimport) | |
|---|---|---|
| 编译阶段 | 编译器知道正在从 DLL 导入符号,可能会进行一些特定的优化,生成的目标文件中包含对 DLL 中符号的引用标记。 | 编译器不确定符号来源,可能不会进行特定优化,生成的目标文件中的符号引用没有明确指向 DLL。 |
| 链接阶段 | 链接器会解析对 DLL 中符号的引用,确保能正确找到对应的 DLL,并将其与可执行文件或库进行链接。 | 链接过程可能会出现无法解析符号的错误,或者可能会错误地链接到其他地方的同名符号,如果没有正确配置链接选项的话。 |
| 运行阶段 | 程序运行时,加载器会根据编译和链接时的信息,正确地加载所需的 DLL,并将程序中的符号引用指向 DLL 中的实际实现。 | 可能会导致程序在运行时无法找到所需的符号,或者加载了错误的符号,从而导致程序崩溃或出现错误行为。 |
使用 __declspec(dllimport) 就仿佛有坐标,而不使用的话只能依靠 lib 中的路径(地图)去找。因此不使用 __declspec(dllimport) 的话,在程序加载时需要依次进行核对,确认指向的 dll 区域是否准确 |