ОБНОВЛЕНИЕ ДЛЯ .NET 4.0 И БОЛЕЕ ПОСЛЕДНИЕ РАМКИ
Это старый вопрос, который задавался во времена .Net 2.0, когда поддержка DLL-библиотек смешанного режима имела серьезные проблемы с инициализацией, склонные к случайным тупикам. Начиная с .Net 4.0, инициализация DLL смешанного режима изменилась. Теперь есть две отдельные стадии инициализации:
- Собственная инициализация, вызываемая в точке входа DLL, которая включает в себя собственную настройку C ++ во время выполнения и выполнение вашего метода DllMain.
- Управляемая инициализация, автоматически выполняемая системным загрузчиком.
Поскольку шаг № 2 выполняется вне блокировки загрузчика, взаимоблокировки отсутствуют. Подробности описаны в Инициализация смешанных сборок .
Чтобы гарантировать, что ваша сборка смешанного режима может быть загружена из собственного исполняемого файла, единственное, что вам нужно проверить, - это то, что метод DllMain объявлен как собственный код. #pragma unmanaged
может помочь здесь:
#pragma unmanaged
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
... // your implementation here
}
Также важно, чтобы любой код, который DllMain мог вызывать прямо или косвенно, также был неуправляемым. Имеет смысл ограничить тип функциональности, используемой DllMain, чтобы вы могли отслеживать весь код, доступный из DllMain, и убедиться, что он весь скомпилирован с #pragma unmanaged
.
Компилятор немного помогает, давая вам предупреждение C4747, если он обнаруживает, что DllMain не объявлен как неуправляемый:
1> Generating Code...
1>E:\src\mixedmodedll\dllmain.cpp : warning C4747: Calling managed 'DllMain': Managed code may not be run under loader lock, including the DLL entrypoint and calls reached from the DLL entrypoint
Однако компилятор не будет генерировать никаких предупреждений, если DllMain косвенно вызовет какую-то другую управляемую функцию, поэтому вы должны убедиться, что этого никогда не произойдет, иначе ваше приложение может случайно заблокироваться.