MSVC DLL 加载: __declspec(dllexport) 函数是直接加载的,没有 DllMain

MSVC DLL loading: are __declspec(dllexport) functions loaded directly without DllMain

我尝试用 VS C++ 编写一个 DLL 项目,其中包含一些导出函数,如下所示:

extern "C"  __declspec(dllexport) int function_sendNumber(unsigned num);

我注意到 VS 项目附带包含 DllMain 入口函数的文件 dllmain.cpp。 但是,我评论了 DllMain 函数并使用 Delphi exe 应用程序来 像下面的函数指针一样调用导出的函数:

function  function_sendNumber(n : Integer): Integer; cdecl;
external 'DLLproject.dll';

Delphi 应用程序成功调用了 DLL 导出函数。 我认为这种方法是 DLL 显式链接。 所以想了解清楚,到底是Explicit Loading还是implicit。 如果是这样,如何在没有 DllMain 的情况下加载导出的函数。 我没有找到任何调用 LoadLibrary 来加载 DLL。

有一些或多或少相关的术语:

  • 显式/隐式链接 - 这有点不合适,因为 .dll 要么被链接(通过.exe 或另一个 .dll) 或不是。更好的术语是 显式/隐式加载 ,因为 .dll 的加载方式:

    1. Explicitly - 按需(使用 LoadLibraryLoadLibraryEx 或其他(较低级别)机制)来自其客户端代码
    2. 隐式ly - 默认情况下(自动,由 Win 在进程启动时 (检查下一个项目符号))。这些 .dll.exe 链接(或另一个 .dll 链接(递归) .exe)
    3. [MS.Docs]: Linker Support for Delay-Loaded DLLs - 在中间满足上述 2 个选项,利用每个选项的优势(意味着 .dll 仍然会自动加载(所以它仍然隐式加载),但仅在需要时(调用其函数之一)而不是进程启动时)
  • [MS.Docs]: DllMain entry point.dll 加载到进程中时正在执行的函数,regardless加载方法(上)

  • function_sendNumber - 由您的 .dll 导出,因为 __declspec(dllexport)(并且名称保持简单(即使代码编译为 C++)因为外部“C”)

  • 您可以从 Delphi 调用函数的事实是因为:

    选中这 3 个项目后,Delphi 完成了(在幕后)链接 .dll 的工作.exe,因此你有 隐式加载 (值得一提的是@HeartWare 的建议,也将函数标记为 delayed 来自 Delphi,以便受益于 Delayed Loading)