4

我为非托管 C++ 库(与 C# 一起使用)制作了非常简单的包装器。Wrapper 有一个非托管类和一个托管类。托管类具有非托管类的私有成员并像那样使用它。

我已经完成了非常简单的设置——我只为一个函数创建了包装器,以查看是否一切正常。但是,一旦我创建了一个包装器实例,我的应用程序就会出现异常“检测到 LoaderLock”,并显示以下消息:

DLL 'c:\path\CPPWrapper.dll' 正在尝试在 OS Loader 锁内进行托管执行。不要尝试在 DllMain 或图像初始化函数中运行托管代码,因为这样做会导致应用程序挂起。

如果我为“LoaderLock”异常关闭中断,我会得到“FileLoadException was unhandled”:

Could not load file or assembly 'CPPWrapper.dll' or one of its dependencies. Exception from HRESULT: 0xE0434352

知道我做错了什么,我该如何解决这个问题?

CPPWrapper.h

// CPPWrapper.h

#pragma once

#include "Native.h"

using namespace System;

namespace CPPWrapper {

    public ref class Class1
    {
        public:

        Class1() : mnt(new Native)
        {

        }

        ~Class1(void)
        {
            // call the finalize method
            this->!Class1();
        }

        // Finalize (for garbage collection)
        !Class1(void)
        {
            // Remove unmanaged class
            delete mnt;
            mnt = NULL;
        }

        void Napravi()
        {
            mnt->CreatePK();
        }

    private:
        Native *mnt;
    };

}
4

2 回答 2

3

我发现解决此问题的正确方法是添加“LoaderLock”异常#pragma unmanageddllmain.c 不要关闭中断。

有关详细信息,请参阅混合程序集的初始化并向下滚动到 DllMain 部分。基本上正在发生的事情是该项目正在将 DllMain 函数编译为托管 (MSIL),但它仅在非托管代码中运行。这#pragma unmanaged会强制将函数编译为非托管函数。

所以我dllmain.c现在是:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

#pragma unmanaged
BOOL APIENTRY DllMain( HMODULE hModule,
                   DWORD  ul_reason_for_call,
                   LPVOID lpReserved
                 )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}
于 2012-09-26T15:59:14.807 回答
0

LoaderLock 的另一个潜在原因是全局静态对象的初始化。就我而言,我正在全局编译 boost::xpressive 正则表达式,当我的 C++/CLI 包装器初始化 DllMain 时,它不喜欢这样做。我不知道为什么,因为它不应该是托管代码,而是将它移动到一个函数静态对象修复它。

于 2018-08-22T13:10:54.523 回答