从 C# 调用非托管 C++ VS 6.0 MFC dll

Posted

技术标签:

【中文标题】从 C# 调用非托管 C++ VS 6.0 MFC dll【英文标题】:Call unmanaged C++ VS 6.0 MFC dll from C# 【发布时间】:2009-12-16 20:03:20 【问题描述】:

我有一个在 VS 6.0 中开发的非托管 C++ MFC dll。我想在我的 C# 应用程序中使用它。我正在尝试使用 PInvoke。

这是 C++ 代码:

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


extern "C" 

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )

    return TRUE;


 __declspec(dllexport) int test(int a)

    return a * a;


这就是我尝试从 C# 调用“test”方法的方式:

// PInvokeTest.cs
using System;
using System.Runtime.InteropServices;

class PlatformInvokeTest


    [DllImport("TestDll.dll")]
    internal static extern int test(int number);

    public static void Main()
    
        Console.WriteLine(test(5));     
    

当我将 C++ dll 设置为普通的 Win32 dll 时,这种方法效果很好。

但是,一旦我将项目类型更改为 MFC(“在共享 DLL 中使用 MFC”),我就会收到此错误:

未处理的异常:System.DllNotFoundException:无法加载 DLL“TestDll.dll”:找不到指定的模块。 (来自 HRESULT 的异常:0x8007007E) 在 PlatformInvokeTest.test(Int32 number)

谢谢!

【问题讨论】:

【参考方案1】:

TestDll.dll 可能无法加载它的依赖 DLL 之一。

尝试在 Depends (Dependency Walker) 实用程序中加载您的 TestDll.dll 文件。 Depends 应该与 VC 6 一起安装,在 Microsoft Visual Studio 6.0 工具下。这将向您显示 DLL 具有哪些依赖项,并在其中一个依赖项失败时进行标记。

确保从与 C# 代码相同的文件夹中加载 TestDll.dll。

请注意,Depends 仅适用于非托管 DLL。

【讨论】:

有效!!!非常感谢! Dependency Walker 正是我所需要的。 TestDll.dll 有一个依赖的 dll - MSVCRTD.DLL。将此 dll 复制到项目文件夹后,C# 应用程序运行良好。 这意味着您依赖于 C++ 运行时。 MSVCRTD 是运行时的调试版本。请务必使用您的发布版本重新分发非调试 dll。【参考方案2】:

DLL 需要位于系统可以拾取它的路径中。你把它放在你的应用程序启动的目录中了吗? (可能在您的 VS 解决方案的 DEBUG 文件夹中)。

第二个选项是给它DLL的绝对路径。

第三个选项是把它放在 "c:\windows\System" 但这是一个 '-1' 方法:D

【讨论】:

谢谢,哈桑。 TestDll.dll 位于 bin 文件夹中(.exe 文件所在的位置)。事实上,当我将 TestDll.dll 编译为常规 Win32 dll 并放置到同一位置时,程序运行良好。仅当我将 dll 编译为 MFC 时才会出现此错误。我想这与依赖关系有关,但我不确定我还应该添加什么以及 MFC dll ...【参考方案3】:

一般来说,当您遇到此类错误时,您可以使用Assembly Binding Log Viewer 来确定 dll 是否由于缺少依赖项而无法加载。

在您的特定情况下,最可能的原因是您将 dll 动态链接到 MFC,并且当 C# 应用程序尝试加载您的 dll 时,它无法加载 MFC dll。

您可以并排复制所需的 MFC dll,也可以切换到将 MFC 静态链接到您的库。

【讨论】:

以上是关于从 C# 调用非托管 C++ VS 6.0 MFC dll的主要内容,如果未能解决你的问题,请参考以下文章

从非托管 c++ 调用托管 c# 函数

从非托管 c++ 调用托管 c# 函数

PInvokeStackImbalance C# 调用非托管 C++ 函数

从非托管 c++ 调用 C# 函数(通过托管包装器)

从 C# 调用 C++ dll。 “无法封送'返回值':托管/非托管类型组合无效。”

让非托管 c++ 代码调用调用 c# 代码的托管 c++ 代码