Вызов управляемого кода из DLLMain
Я пишу неуправляемую DLL (с C++ и WinAPI), но я хочу использовать некоторые методы C#, поэтому я создал оболочку с использованием C++/CLI.
Но проблема в том, что неуправляемая dll будет "введена" (LoadLibrary), и я застрял здесь, не зная, как я могу вызывать функции Wrapper.
Неуправляемый код:
#include <Windows.h>
//the function I want to call
__declspec(dllexport) void SimpleTest(int *p);
extern "C" __declspec(dllexport) void MyEntryPoint()
{
int* test;
SimpleTest(test);
}
BOOL WINAPI DllMain(/*DllMain parameters*/)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
MyEntryPoint();
break;
}
return TRUE;
}
Оболочка (C++/CLI):
__declspec(dllexport) void SimpleTest(int* p)
{
*p = 1;
}
Я не знаю, что здесь происходит. Среда.NET не была загружена? DLL-архиватор не был загружен? (Я перебрал модули, а обертки там не было).
Нужно ли инициализировать CLR вручную?
Я читал о блокировке загрузчика, но я не уверен, что это проблема здесь.
2 ответа
От документации до DllMain
:
Существуют значительные ограничения на то, что вы можете безопасно делать в точке входа DLL. См. Общие рекомендации для конкретных API-интерфейсов Windows, которые небезопасны для вызова в DllMain. Если вам нужно что-то кроме самой простой инициализации, сделайте это в функции инициализации для DLL. Вы можете требовать, чтобы приложения вызывали функцию инициализации после запуска DllMain и до того, как они вызовут любые другие функции в DLL.
Вызов в управляемый код - одна из тех вещей, которые вы не можете сделать!
Стандартный способ справиться с этим - создать поток в DllMain
разрешенное действие и вызов управляемого кода из этого потока.
Dlls и общие объекты имеют проблемную жизнь в стандартах C/C++.
Операционная система загружает DLL, вызывает DllMain, инициализирует глобальные переменные, затем загружает зависимые DLL.
Это означает, что a) во время создания DllMain/global у вас есть блокировка загрузчика b) зависимые библиотеки DLL могут не загружаться.
Это означает, что CLR может быть неактивен (не инициализирован) и может зависать, если требуется блокировка загрузчика.
Откладывание на потом - лучшее решение.
class ImportantOnceWork{
ImportantOnceWork()
{
MyEntryPoint();
}
};
int DoOnce()
{
static ImportantOnceWork val;
}
Затем вызовите DoOnce(); в каждой точке крючка.