【发布时间】:2015-07-16 16:02:53
【问题描述】:
我在 PInvoking SetupDiCreateDeviceInfoList 时发现了这一点。
C++ 函数签名是:
HDEVINFO SetupDiCreateDeviceInfoList(
_In_opt_ const GUID *ClassGuid,
_In_opt_ HWND hwndParent
);
在 C# 中,我定义了这样的 GUID 结构:
[StructLayout(LayoutKind.Sequential)]
public struct GUID
{
public uint Data1;
public ushort Data2;
public ushort Data3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data4;
}
还有这样的功能:
[DllImport("Setupapi.dll")]
public static extern IntPtr SetupDiCreateDeviceInfoList(GUID ClassGuid, IntPtr hwndParent);
由于在 C# 中结构默认通过副本传递(与类不同),因此此函数签名不应匹配。确实在 32 位运行时调用函数时:
GUID classGuid = new GUID();
IntPtr deviceInfoSet = SetupDiCreateDeviceInfoList(classGuid, IntPtr.Zero);
我收到一个错误:
SetupDiCreateDeviceInfoList' 使堆栈失衡。这很可能 因为托管的 PInvoke 签名与非托管的不匹配 目标签名。检查调用约定和参数 PInvoke 签名与目标非托管签名匹配。
但在 64 位运行时,上面的代码可以工作。为什么???
当然,如果我改为通过引用传递结构,该函数在 32 位和 64 位运行时都可以正常工作:
[DllImport("Setupapi.dll")]
public static extern IntPtr SetupDiCreateDeviceInfoList(ref GUID ClassGuid, IntPtr hwndParent);
GUID classGuid = new GUID();
IntPtr deviceInfoSet = SetupDiCreateDeviceInfoList(ref classGuid, IntPtr.Zero);
【问题讨论】:
-
@PeterDuniho 在 x64 上,我收到一个指向设备信息集的有效指针。我是在64位环境下开发的,每次都成功安装了驱动。当我决定在 32 位环境中进行测试时,我才发现错误的函数签名。
标签: c# winapi data-structures pinvoke marshalling