加载DLL和直接调用之间的区别

时间:2018-06-17 06:35:19

标签: c++

我认为非常愚蠢,但我无法理解,

例如,我想使用Windows API,如GetWindowsDirectory,GetSystemInfo等...我可以直接使用Api或通过GetProcAddress调用:

方法1 在这里,我可以使用LoadLibrary和GetProcAddress调用API:

#include <windows.h>

typedef UINT (WINAPI *GET_WIN_DIR)(LPWSTR lpBuffer, UINT size);

TCHAR infoBuffer[MAX_PATH + 1];
HINSTANSE dllLoad = LoadLibrary("Kernel32.dll");
GET_WIN_DIR function = (GET_WIN_DIR )GetProcAddress(dllLoad, "GetWindowsDirectoryW");

int result = function2(infoBuffer, MAX_PATH + 1);

方法2 在这里我可以直接调用像GetWindowsDirectory这样的API:

#include <windows.h>

TCHAR infoBuffer[MAX_PATH + 1];
GetWindowsDirectory(infoBuffer, MAX_PATH);

我有2个问题:

  1. 上述两种方法有什么区别?

  2. 是否加载库对可执行文件的影响?(。exe)(我做了测试,但它改变了?)

2 个答案:

答案 0 :(得分:4)

Microsoft致电

  • 方法1 ...显式链接
  • 方法2 ...隐式链接

来自MSDN Linking an Executable to a DLL

  

隐式链接有时称为静态加载或加载时动态链接。显式链接有时称为动态加载或运行时动态链接。

     

使用隐式链接,使用DLL的可执行文件链接到DLL制造商提供的导入库(.lib文件)。操作系统在加载使用它的可执行文件时加载DLL。客户端可执行文件调用DLL的导出函数,就像函数包含在可执行文件中一样。

     

使用显式链接,使用DLL的可执行文件必须进行函数调用以显式加载和卸载DLL并访问DLL的导出函数。客户端可执行文件必须通过函数指针调用导出的函数。

     

可执行文件可以使用与链接方法相同的DLL。此外,这些机制不是互斥的,因为一个可执行文件可以隐式链接到DLL而另一个可以显式附加到它。

在我们的项目中,我们在任何常见情况下使用隐式链接。

我们在两种情况下使用显式链接:

  1. 用于在运行时明确加载的插件DLL
  2. 在隐式链接函数不正确的特殊情况下。
  3. 如果我们使用自身链接到其他DLL的不同版本(例如来自Microsoft)的DLL,则可能发生2 nd 情况。当然,这有点关键。实际上,我们试图阻止2 nd 的情况。

答案 1 :(得分:3)

不,我认为这根本不是傻瓜。如果你不明白,请问。这就是这个网站的用途。也许你会被投票,谁知道,但不是我。与领土同行。没有痛苦,没有收获,问我怎么知道。

无论如何,@ Sherf称之为“显式链接”的主要目的是双重的:

  1. 如果你不确定你想要使用的DLL是否会在运行时出现在机器上(尽管你也可以使用/DELAYLOAD这样更方便)。

  2. 如果您不确定要调用的功能是否存在于(例如)您希望运行应用程序的所有Windows版本中。

  3. 关注第1点,其中一个示例可能是读取或写入WMA文件。某些旧版本的Windows默认情况下不包含WMA支持(我们在这里可以追溯到很长一段时间)如果您隐式链接到WMA.DLL,那么如果它不存在,您的应用程序将无法启动。使用显式链接(或/ DELAYLOAD)可以让你在运行时检查这一点,如果它仍然缺失,则会发出礼貌消息,同时仍允许你的应用程序的其余部分正常运行。

    对于第2点,例如,您可能希望使用LoadIconWithScaleDown()函数,因为它通常会产生比LoadIcon()更好的缩放图标。但是,如果您只是盲目地调用它,那么,您的应用程序将不再在XP上运行,因为XP不支持它,因此您可以通过GetProcAddress()有条件地调用它,如果它可用并且回退到{{ 1}}如果没有。

    好的,为了完善,与DELAYLOAD有什么关系?好吧,这是一个linker switch,它允许您告诉链接器哪个DLL对您的应用程序是可选的。一旦你完成了,那么你可以这样做:

    LoadIcon()

    这很漂亮。

    所以我希望您现在可以看到这个问题实际上是关于显式链接的实用程序与所涉及的不便(所有这些都以/ DELAYLOAD的方式进行)。对我来说,幕后发生的事情并不那么有趣。

    是的,就程序的行为方式而言,最终结果是相同的。明确的链接或延迟加载可能涉及一个小的(读取:微小的)性能开销,但我真的不会担心这一点,并且延迟加载涉及一些潜在的“陷阱”(这不会影响大多数正常凡人)详细{{{ 3}}