我为非托管C ++库做了非常简单的包装(与C#一起使用)。 Wrapper有一个非托管类和一个托管类。托管类具有非托管类的私有成员,并使用它。
我做了非常简单的设置 - 我只为一个函数创建了包装器,看看是否一切正常。但是,只要我创建了一个包装器实例,我的应用程序就会检测到“检测到LoaderLock”,并显示以下消息:
DLL'c:\ path \ CPPWrapper.dll'是 在OS Loader锁中尝试托管执行。不要试图 在DllMain或图像初始化函数中运行托管代码 因为这样做会导致应用程序挂起。
如果我关闭“LoaderLock”异常,我会收到“FileLoadException未处理”:
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;
};
}
答案 0 :(得分:3)
我发现解决此问题的正确方法是在#pragma unmanaged
中添加dllmain.c
,不要因为“LoaderLock”异常而关闭。
有关详情,请参阅Initialization of Mixed Assemblies并向下滚动至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;
}
答案 1 :(得分:0)
LoaderLock的另一个潜在原因是初始化全局静态对象。就我而言,我正在全局编译一个boost :: xpressive regex,当我的C ++ / CLI包装器初始化DllMain时,它不喜欢这样做。我不知道为什么,因为它不应该是托管代码,但是将其移动到功能静态对象中可以对其进行修复。