从 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的主要内容,如果未能解决你的问题,请参考以下文章
PInvokeStackImbalance C# 调用非托管 C++ 函数