为什么在我从 C# 代码调用导入的 C++ 函数时抛出 AccessViolationException?

Why is an AccessViolationException thrown when I call an imported C++ function from C# code?

我已经阅读了很多关于该主题的帖子,但我还没有找到解决我的问题的方法。

在我的 C# 代码中,我尝试使用 DllImport 调用 C++ 函数。不幸的是,我没有 C++ 代码,但头文件提供了有关函数的信息:

ABCD Initialize
(
  IN FLOAT a  
  , IN DWORD b  
);  

头文件中也定义了ABCD:

#define EFGH extern "C"
...
#define ABCD EFGH __declspec(dllexport) HRESULT WINAPI

在 C# 代码中,我尝试这样调用 Initialize 函数:

[DllImport("path.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 Initialize([In] float a, [In] UInt32 b);
...
Initialize(50.0f, 0);

根据 this site,数据类型 float 不需要编组,我可以使用 UInt32 而不是 DWORD。对于 return 类型 HRESULT WINAPI,我使用数据类型 UInt32,据我所知,也不需要编组吗? (我也尝试使用其他数据类型作为参数和 return 值,但总是出现相同的异常)

对于DllImport属性,已经测试了CharSetCallingConventions的多种可能性,但我没有成功。在声明函数时,我还尝试了两种变体,有和没有参数的 [In] 属性。

函数调用时抛出异常:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

我是不是漏掉了什么?成功调用函数的下一步是什么?

谢谢。


这是完整的 C# 代码。如前所述,我没有用于构建 .dll 文件的代码。我也不允许共享 dll。

using System;
using System.Runtime.InteropServices;

namespace MyNamespace
{
  class Program
  {
    [DllImport("path.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern UInt32 Initialize([In] float a, [In] UInt32 b);

    static void Main(string[] args)
    {
      Initialize(50.0f, 0); // <- throws System.AccessViolationException
      Console.ReadLine();
    }
  }
}

终于可以确定问题了

为了检查参数的数据类型和return值,我在dll上使用了反编译器Snowman。看起来 dll 只定义了接口,而实现在开发人员忘记首先发送的另一个 dll 文件中。

一旦第二个 .dll 文件存储在我的程序的运行时文件夹中,函数调用就会起作用。我还想提一下,调用在有和没有 [In] 参数属性的情况下都有效。

虽然我不知道抛出异常的确切原因AccessViolationException: Attempted to read or write protected memory...(我认为另一个异常更适合这里),但我很高兴问题能够得到解决。

感谢 Ben VoigtDavid Heffernan 的评论!