Clr Dll 由测试程序加载但不通过调用应用程序加载
Clr Dll loaded by test prog but not by calling app
我想为程序 (EXE) 开发插件以与外部 C# 模块互操作。该插件是所需的三个 dll 之一:此 dll (A) 调用包装器 dll(Native/Managed,在 C++/Cli 中)(B) 以与 C# dll (C) 互操作。
A 应该在部署时由调用程序 (EXE) 加载。
在测试中,显示了一条来自 C# dll 的消息,告诉我 dll A 已被 C++ 测试人员正确加载,随后成功调用了其他 dll。
在部署中,dll A如果只显示一条消息,则由EXE加载。但是,当添加调用dll B的代码行时,EXE不再识别dll A。
我已确保所有文件都在正确的位置。所以我认为问题在于调用 dll B 的额外互操作代码行。知道我应该在哪里寻找问题吗?
这里是dll A中导出的函数:
int WINAPI Init()
{
FILE * pConsole;
AllocConsole();
freopen_s(&pConsole, "CONOUT$", "wb", stdout);
printf("Started\n");
//These two line below call the wrapper dll B
// which serves as a middle man between dlls A and C
NativeExport_ClientWrapper* client = createMyClass();
if (client) client->Test();
return 1;
}
这是包装器 B 的非托管端:
//----------------------------------------------
//NativeExport_ClientWrapper.h
//----------------------------------------------
//#pragma once
#pragma once
#pragma unmanaged
#define THISDLL_EXPORTS
#ifdef THISDLL_EXPORTS
#define THISDLL_API __declspec(dllexport)
#else
#define THISDLL_API __declspec(dllimport)
#endif
class ILBridge_ClientWrapper;
class NativeExport_ClientWrapper {
private:
ILBridge_ClientWrapper* __bridge;
public:
NativeExport_ClientWrapper();
public:
~NativeExport_ClientWrapper();
public:
THISDLL_API void Test();
};
extern "C" THISDLL_API NativeExport_ClientWrapper* createMyClass();
这是包装器的托管端:
//----------------------------------------------
//ILBridge_ClientWrapper.h
//----------------------------------------------
#pragma once
#pragma managed
#include <vcclr.h>
class ILBridge_ClientWrapper {
private:
gcroot<Client^> __Impl;
public:
ILBridge_ClientWrapper() {
__Impl = gcnew Client;
}
void Test() {
__Impl->test();
}
};
经过详尽的搜索,我没有找到任何有助于解决此问题的方法,包括进行库加载调试。
我的其他相关帖子在这里:Unexpected Whosebug exception using CLR in a dll
最后,通过做几件事,这个异常消失了,现在一切正常了:
1) 在我的 CS 项目中,我使用 unmanagedexports 包(使用 NuGet 包管理器安装它:Install-Package unmanagedexports)以使用 __stdcall 调用约定导出静态方法。在这个项目中,你需要添加这些:
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
2) 将包装器头文件的路径添加到非托管 C/C++ 项目的 属性 页面(C/C++->general->additional include directories)
3) 将托管和本机包装器合并为一个 project/dll(使用 /clr 选项构建),将它们与其他两个模块分开(一个用于托管 C#,一个用于非托管 C/C++)
4) 可选地,我为非托管 C/C++ 函数添加了一个定义文件
5) 确保所有模块都是针对相同的框架和平台构建的。就我而言,我使用 framework 4.0 和 x86 平台。在某些情况下,您需要添加一个包含以下内容的 app.config 文件:
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>"
6) 设置环境中指向dll部署位置的路径
就是这样。
我想为程序 (EXE) 开发插件以与外部 C# 模块互操作。该插件是所需的三个 dll 之一:此 dll (A) 调用包装器 dll(Native/Managed,在 C++/Cli 中)(B) 以与 C# dll (C) 互操作。
A 应该在部署时由调用程序 (EXE) 加载。
在测试中,显示了一条来自 C# dll 的消息,告诉我 dll A 已被 C++ 测试人员正确加载,随后成功调用了其他 dll。
在部署中,dll A如果只显示一条消息,则由EXE加载。但是,当添加调用dll B的代码行时,EXE不再识别dll A。
我已确保所有文件都在正确的位置。所以我认为问题在于调用 dll B 的额外互操作代码行。知道我应该在哪里寻找问题吗?
这里是dll A中导出的函数:
int WINAPI Init()
{
FILE * pConsole;
AllocConsole();
freopen_s(&pConsole, "CONOUT$", "wb", stdout);
printf("Started\n");
//These two line below call the wrapper dll B
// which serves as a middle man between dlls A and C
NativeExport_ClientWrapper* client = createMyClass();
if (client) client->Test();
return 1;
}
这是包装器 B 的非托管端:
//----------------------------------------------
//NativeExport_ClientWrapper.h
//----------------------------------------------
//#pragma once
#pragma once
#pragma unmanaged
#define THISDLL_EXPORTS
#ifdef THISDLL_EXPORTS
#define THISDLL_API __declspec(dllexport)
#else
#define THISDLL_API __declspec(dllimport)
#endif
class ILBridge_ClientWrapper;
class NativeExport_ClientWrapper {
private:
ILBridge_ClientWrapper* __bridge;
public:
NativeExport_ClientWrapper();
public:
~NativeExport_ClientWrapper();
public:
THISDLL_API void Test();
};
extern "C" THISDLL_API NativeExport_ClientWrapper* createMyClass();
这是包装器的托管端:
//----------------------------------------------
//ILBridge_ClientWrapper.h
//----------------------------------------------
#pragma once
#pragma managed
#include <vcclr.h>
class ILBridge_ClientWrapper {
private:
gcroot<Client^> __Impl;
public:
ILBridge_ClientWrapper() {
__Impl = gcnew Client;
}
void Test() {
__Impl->test();
}
};
经过详尽的搜索,我没有找到任何有助于解决此问题的方法,包括进行库加载调试。
我的其他相关帖子在这里:Unexpected Whosebug exception using CLR in a dll
最后,通过做几件事,这个异常消失了,现在一切正常了:
1) 在我的 CS 项目中,我使用 unmanagedexports 包(使用 NuGet 包管理器安装它:Install-Package unmanagedexports)以使用 __stdcall 调用约定导出静态方法。在这个项目中,你需要添加这些:
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
2) 将包装器头文件的路径添加到非托管 C/C++ 项目的 属性 页面(C/C++->general->additional include directories)
3) 将托管和本机包装器合并为一个 project/dll(使用 /clr 选项构建),将它们与其他两个模块分开(一个用于托管 C#,一个用于非托管 C/C++)
4) 可选地,我为非托管 C/C++ 函数添加了一个定义文件
5) 确保所有模块都是针对相同的框架和平台构建的。就我而言,我使用 framework 4.0 和 x86 平台。在某些情况下,您需要添加一个包含以下内容的 app.config 文件:
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>"
6) 设置环境中指向dll部署位置的路径
就是这样。