1

我正在编写一个非托管 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 环境没有加载?Wrapper DLL 没有加载?(我遍历了模块并且包装器不存在)。

我必须手动初始化 CLR 吗?

我阅读了有关加载程序锁定的信息,但我不确定这是否是这里的问题。

4

2 回答 2

3

从文档到DllMain

在 DLL 入口点中可以安全地执行的操作有很大的限制。有关在 DllMain 中调用不安全的特定 Windows API,请参阅一般最佳实践。如果您需要除了最简单的初始化之外的任何其他内容,请在 DLL 的初始化函数中执行此操作。您可以要求应用程序在 DllMain 运行之后和调用 DLL 中的任何其他函数之前调用初始化函数。

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

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

于 2015-12-21T21:39:00.667 回答
0

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

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

这意味着 a) 在 DllMain/全局构建期间,您有加载程序锁定 b) 依赖 DLL 可能不会被加载。

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

推迟到以后是最好的解决方案。

class ImportantOnceWork{
    ImportantOnceWork()
     {
         MyEntryPoint();

     }
};

int DoOnce()
{
    static ImportantOnceWork val;
}

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

于 2015-12-21T21:51:20.973 回答