【发布时间】:2020-03-16 16:32:05
【问题描述】:
我已经阅读了许多关于该主题的主题,但我还没有找到解决问题的方法。
在我的 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。对于返回类型HRESULT WINAPI,我使用数据类型UInt32,据我了解,也不需要编组? (我也尝试使用其他数据类型作为参数和返回值,但总是得到相同的异常)
对于 DllImport 属性,已经测试了CharSet 和CallingConventions 的许多可能性,但我没有成功。在声明函数时,我还尝试了这两种变体,有和没有参数的[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();
}
}
}
【问题讨论】:
-
如此处所述,该代码是正确的。我敢打赌,当您从真实代码更改某些内容时,您转录了某些内容。提交minimal reproducible example。
-
感谢您的评论!不幸的是,我不允许共享 .dll 文件,因此我无法提供可重现的示例。 C# 代码已接近完成,命名空间由一个带有 Main 函数的类组成,该函数仅调用
Initialize(50.0f, 0);。 -
当然你可以分享一个可重现的例子。切掉任何敏感的东西。
-
@DavidHeffernan 我编辑了问题并添加了完整的 C# 代码。不幸的是,我没有用于构建 C++ dll 的代码。此外,我不允许共享 .dll 文件或其中的一部分。头文件的(我猜的)相关部分可以在问题中找到。不幸的是,我不允许发布完整的 .h 文件。希望有帮助。感谢您的宝贵时间。
-
@luk:我可以向您保证这里不需要
[In],从而为您节省一些组合来尝试。这是 x86 或 x64 代码还是其他架构?有些人比其他人更关心调用约定。WINAPI应该像您的 p/invoke 已经指定的那样为您设置 stdcall。
标签: c# c++ marshalling dllimport access-violation