Search code examples
delphidlldllexportdllmain

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


I tried to write a DLL project in VS C++ with some exported functions like below:

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

I noticed VS project comes with file dllmain.cpp containing DllMain entry function. However, i commented the DllMain function and use Delphi exe application to call the exported functions like below function pointer:

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

The Delphi application successfully called the DLL exported function. I thought this method is DLL Explicit linking. So I want to understand clearly, is it Explicit Loading or implicit. If so how exported functions are loaded without DllMain. I don't find any calls to LoadLibrary to load DLL.


Solution

  • There are a number of terms that are more or less connected:

    • Explicit / Implicit Linking - this is kind of improper, because a .dll is either linked (by an .exe or another .dll) or not. A better term would be Explicit / Implicit Loading, because of the way a .dll is loaded:

      1. Explicitly - on demand (using LoadLibrary, LoadLibraryEx, or other (lower level) mechanism) from its client code
      2. Implicitly - by default (automatically, by Win at process startup (check next bullet)). These .dlls are linked by the .exe (or another .dll linked (recursively) by the .exe)
      3. [MS.Docs]: Linker Support for Delay-Loaded DLLs - meet the above 2 options in the middle, taking the advantages from each (meaning that the .dll will still be loaded automatically (so it's still Implicit Loading), but only at the point when it's needed (one of its functions called), instead of process startup)
    • [MS.Docs]: DllMain entry point the function that it's being executed when a .dll is loaded into a process, regardless of the load method (above)

    • function_sendNumber - is exported by your .dll because of __declspec(dllexport) (and the name is kept simple (even if code is compiled as C++) because of extern "C")

    • The fact that you can call the function from Delphi is because:

      With these 3 items checked, Delphi did the (under the hood) work of linking the .dll by the .exe, and as a consequence you have Implicit Loading (worth mentioning @HeartWare's suggestion to also mark a function as delayed from Delphi, in order to benefit from Delayed Loading)