Я пишу неуправляемые 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 вручную?
Я читал о блокировке загрузчика, но я не уверен, что это проблема здесь.
От документации до DllMain
:
Существуют значительные ограничения на то, что вы можете безопасно делать в точке входа DLL. См. Общие рекомендации для конкретных API-интерфейсов Windows, которые небезопасны для вызова в DllMain. Если вам нужно что-то кроме самой простой инициализации, сделайте это в функции инициализации для DLL. Вы можете требовать, чтобы приложения вызывали функцию инициализации после запуска DllMain и до того, как они вызовут любые другие функции в DLL.
Вызов в управляемый код — одна из тех вещей, которые вы не можете сделать!
Стандартный способ справиться с этим — создать поток в DllMain
разрешенное действие и вызов управляемого кода из этого потока.
Dlls и общие объекты имеют проблемную жизнь в стандартах C / C ++.
Операционная система загружает DLL, вызывает DllMain, инициализирует глобальные переменные, затем загружает зависимые DLL.
Это означает, что
а) во время создания DllMain / global у вас есть блокировка загрузчика
б) зависимые DLL не могут быть загружены.
Это означает, что CLR может быть неактивен (не инициализирован) и может зависать, если требуется блокировка загрузчика.
Откладывание на потом — лучшее решение.
class ImportantOnceWork{
ImportantOnceWork()
{
MyEntryPoint();
}
};
int DoOnce()
{
static ImportantOnceWork val;
}
Затем вызовите DoOnce (); в каждой точке крючка.