【问题标题】:Exception Info: System.AccessViolationException when calling C++ Dll异常信息:调用 C++ Dll 时出现 System.AccessViolationException
【发布时间】:2020-05-14 22:56:00
【问题描述】:

我正在尝试让非托管 C++ DLL 与我的 C# 项目一起使用,当通过 VS2019 中的调试器运行程序时,代码可以正常工作。在没有调试器的情况下运行时,应用程序在运行时崩溃,并且事件查看器在调用 C++ Dll 时给我异常信息:System.AccessViolationException

我已经尝试改变我使用 p/invoke 的方式,但我所拥有的可能会使它起作用。 C++ 不是我的强项,但 DLL 并不复杂,它只是一个返回字符串的 if 语句。

有人能看到我在哪里出错了吗?或者提供有关如何解决此问题的任何提示?

C#

[DllImport("unmanaged.dll", EntryPoint = "checkCPU", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr checkCPU();

// to call it

 string check = Marshal.PtrToStringAnsi(checkCPU());

C++

extern "C" __declspec(dllexport) std::string checkCPU()
{

    if (InstructionSet::SSE41() || InstructionSet::SSE42()) {
        return "true";
    }
    else {
        return "false";
    }

}

(我知道这个问题已经被问过好几次了,在互联网上翻遍之后,我没有找到任何可以帮助我的东西。)

编辑

DLL 和项目都是 x86,具有相同的网络框架

【问题讨论】:

  • 您是否检查过该程序是否有权访问 DLL 文件?我的意思是,DLL 文件是否位于程序可以在不需要任何特殊权限的情况下加载它的位置?另外,您想通过调用本机代码来实现什么目标?您这样做的原因是什么?
  • 从 DLL 函数返回 std::string 很可能会失败,即使调用它的语言是 C++,更不用说 C#。您的函数工作的唯一方法是如果调用语言是 C++,调用您的函数的应用程序是使用相同的 C++ 编译器使用相同的构建选项构建的,运行时使用的库是 DLL 版本。
  • std::string in C#?的可能重复
  • @MindSwipe 该程序可以访问 dll,它位于同一目录中。基本上该程序是一个审计工具,对主程序的要求之一是用户 CPU 支持指令集 SSE4.1 - 我认为实现这一点的唯一现实方法是通过使用 CPUID
  • 停止返回只有C++ 知道的类型,例如bool。 C++ 中的 bool 与 C# 中的 bool 不同。 C++ 中的bool 的大小由使用的编译器确定。例如,您应该使用具有公认大小的已知类型,例如 int32_t(32 位 int)。

标签: c# c++ pinvoke dllimport dllexport


【解决方案1】:

感谢大家的cmets,其实是我有点笨。

C++ 需要是 BOOL 而不是 bool。

c# 是 bool 很好。

现在有一个新的问题但是进步了。

再次感谢。

【讨论】:

  • 您实际上可以告诉封送器在属性中使用 C++ bool。
  • @Mgetz 对于返回值 IIRC 来说不容易,我认为BOOL 实际上是最简单的方法
  • @DavidHeffernan 是的,我刚刚仔细检查过,您可以做到...但不能保证便携。
【解决方案2】:

您不能使用 pinvoke 返回像 std::string 这样的 C++ 对象。有多种选项可用于使用 pinvoke 向调用者返回文本:

  1. 返回一个 COM BSTR。
  2. 返回一个由被调用者分配的 C 字符串。调用者将需要释放它。通过使用共享堆或导出释放函数。
  3. 让调用者分配文本缓冲区,并让被调用者填充它。

所有这些方法的示例都可以通过网络搜索轻松找到。

我假设您的代码是一个简化的示例,但如果您真的只想指示成功或失败,那么您可以通过返回布尔类型来完全回避问题。

【讨论】:

  • 或者,在这种情况下,OP 可以简单地返回 bool 而不是 true/false 作为字符串
  • 尝试使用 bool,同样的错误 - 我会考虑返回 COM BSTR
  • 不,不要。如果您只需要一个布尔值,请执行此操作。更简单。
  • 最有可能出现同样的错误,因为bool也是C++类型,只有使用的C++编译器知道。
猜你喜欢
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多