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部署位置的路径

就是这样。