Не потворствуя или избегая использования объектов C ++ в качестве глобальных переменных / статики в вашей DLL, вот информация, которую вы ищете.Порядок операций:
- C / C ++ глобальная / статическая инициализация
DllMain
DllGetClassObject
документация здесь описывает взаимосвязь между глобальной / статической инициализацией C / C ++ и DllMain
.
... При связывании с DLL код VCRuntime предоставляет внутреннюю запись DLL-точечная функция с именем _DllMainCRTStartup
, которая обрабатывает сообщения ОС Windows в DLL для присоединения или отсоединения от процесса или потока.Функция _DllMainCRTStartup
выполняет важные задачи, такие как настройка безопасности стекового буфера, инициализация и завершение C-библиотеки времени выполнения (CRT) и вызовы конструкторов и деструкторов для статических и глобальных объектов ._DllMainCRTStartup
также вызывает функции подключения для других библиотек, таких как WinRT, MFC и ATL, для выполнения их собственной инициализации и завершения.Без этой инициализации CRT и другие библиотеки, а также ваши статические переменные остались бы в неинициализированном состоянии ...
... При подключении к процессу функция _DllMainCRTStartup
устанавливает проверки безопасности буфераинициализирует CRT и другие библиотеки, инициализирует информацию о типе времени выполнения, инициализирует и вызывает конструкторы для статических и нелокальных данных , инициализирует локальное хранилище потока, увеличивает внутренний статический счетчик для каждого присоединения и *Затем 1029 * вызывает пользовательского или библиотечного DllMain
...
Вы можете увидеть все это самостоятельно, установив точку останова в вашем DllMain
, а затем посмотрев на стеккадры, которые приводят к вызову DllMain
.Вы обнаружите, что много интересного сделано еще до того, как ваш DllMain
даже вызван.
Что касается DllGetClassObject
: эта экспортированная функция не вызывается магией.Вызывающий эту функцию должен сделать 3 вещи - загрузить вашу DLL (например, LoadLibrary
), найти адрес функции, загруженной из DLL (например, GetProcAddress
), а затем вызвать этот адрес, используя известную сигнатурудля DllGetClassObject
реализаций.Вы можете делать все это вручную, но такие функции, как CoCreateInstance
, автоматически выполняют эти три действия в порядке, описанном здесь.DllMain
вызывается автоматически при вызове LoadLibrary
, а LoadLibrary
не возвращается до тех пор, пока не вернется DllMain
.Если DllMain
возвращает код успеха, то вызывающий LoadLibrary
получит HMODULE
для DLL.Если DllMain
возвращает код ошибки, у вызывающего абонента никогда не будет HMODULE
для DLL (LoadLibrary
вернет NULL
), и, следовательно, вызывающий не сможет даже найти вашу функцию DllGetClassObject
, тем более вызвать ее.