从 DLLMain 调用托管代码

Calling managed code from DLLMain

我正在编写一个非托管 dll(使用 C++ 和 WinAPI),但我想使用一些 C# 方法,因此,我使用 C++/CLI 创建了一个包装器。

但问题是:非托管 dll 将是 'injected' (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 环境没有加载? Wrapper DLL 没有加载? (我遍历了模块,但包装器不存在)。

我必须手动初始化 CLR 吗?

我读到有关加载程序锁的信息,但我不确定这是否是问题所在。

从文档到 DllMain

There are significant limits on what you can safely do in a DLL entry point. See General Best Practices for specific Windows APIs that are unsafe to call in DllMain. If you need anything but the simplest initialization then do that in an initialization function for the DLL. You can require applications to call the initialization function after DllMain has run and before they call any other functions in the DLL.

调用托管代码是您不能做的事情之一!

处理此问题的标准方法是在 DllMain 中创建一个线程,一个允许的操作,然后从该线程调用托管代码。

Dll 和共享对象在 C/C++ 标准中存在问题。

操作系统加载一个DLL,调用DllMain初始化全局变量,然后加载依赖的DLL。

这意味着 a) 在 DllMain/global 施工期间你有装载机锁 b) 可能未加载依赖的 DLL。

这意味着 CLR 可能未处于活动状态(未初始化)并且如果它需要加载程序锁可能会挂起。

最好的办法是推迟。

class ImportantOnceWork{
    ImportantOnceWork()
     {
         MyEntryPoint();

     }
};

int DoOnce()
{
    static ImportantOnceWork val;
}

然后调用DoOnce();在每个挂钩点。