从 C++ 调用 C DLL 会导致访问冲突,但 C# 项目与 DllImport 工作
Posted
技术标签:
【中文标题】从 C++ 调用 C DLL 会导致访问冲突,但 C# 项目与 DllImport 工作【英文标题】:Calling C DLL from C++ gives Access Violation but C# project with DllImport working 【发布时间】:2016-07-17 18:24:19 【问题描述】:我有一个需要集成的 32 位第 3 方 C DLL,但遇到了一个难以理解/追踪的错误。
我可以编译并成功链接一个简单的 C++ 32 位应用程序,其中包含以下内容:
#include "stdafx.h"
#include <windows.h>
extern "C" int __stdcall external_method(int cardno);
int main()
int n = external_method(0);
return 0;
当我尝试在调试模式下运行应用程序时,它会给出以下信息:
Unhandled exception at 0x100AADF5 (ExternalModule.dll) in
ConsoleApplication2.exe: 0xC0000005: Access violation reading location 0x00000000.
但是,如果我创建一个使用 DllImport/PInvoke 调用相同函数的简单 C# 应用程序,它运行良好:
namespace ConsoleApplication3
class Program
[DllImport("ExternalModule.dll")]
public static extern int external_method(int n);
static void Main(string[] args)
external_method(0);
Debug.WriteLine("YES!");
我正在努力理解一个可以工作而另一个失败的原因。不幸的是,我无权联系 C DLL 的开发人员。
非常感谢任何帮助。
更新感谢 cmets。这是该方法的头文件条目:
int __stdcall exernal_method(int cardno);
我有理由确定调用约定是可以的。正在加载 DLL,因为使用 DLL 的调试版本,我可以看到它在失败之前向调试输出输出了一些消息。
在退出方法时堆栈被损坏可能是一个问题吗?我尝试了几种不同的调用约定,但这是链接器能够使用的唯一一种。
【问题讨论】:
不是 C# 用户,但可能是调用约定不匹配? 你的 C# 和你的 C 代码没有区别。您将不得不寻找环境原因。还有一个电话号码。 会不会是您的 C++ 程序找不到 DLL 或找到不同的版本?链接器可能只是链接到一个导入库,所以它不会抱怨。 调试器或者它没有发生 【参考方案1】:堆栈损坏的可能性不大。
一个可能的原因是不同的 DLL 加载方法。您的 C++ 应用程序静态加载它(Windows 在进程启动之前加载您的 DLL),C# 动态加载(CLR 在进程开始运行后加载 DLL)。要验证这个假设,请从链接器中删除 ExternalModule.lib,将您的 C++ 代码更改为调用 LoadLibrary 和 GetProcAddress。
另一个可能的原因是 C# 运行时初始化 COM,而 C++ 应用程序没有初始化,并且您的 DLL 尝试使用 COM。在您的 C++ 应用程序中,尝试在您的 exernal_method 之前添加 CoInitialize[Ex]。
【讨论】:
这是第二个原因!谢谢 @jugglingcats 不客气。也不要忘记 CoUninitialize。通常应该在线程退出之前完成。以上是关于从 C++ 调用 C DLL 会导致访问冲突,但 C# 项目与 DllImport 工作的主要内容,如果未能解决你的问题,请参考以下文章
运行使用 /clr 构建的 DLL 的本机 C++ 应用程序时访问冲突
从 Delphi“访问冲突”正确调用 DLL 中的 C++ 函数