如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?

What happens if a string in a struct is longer or shorter than the p/Invoked signature used?

本文关键字:什么情况 调用 字符串 结构 如果      更新时间:2023-10-16

举个例子,我想使用C#中的DEV_BROADCAST_DEVICEINTERFACE_A。但是,我不确定如何声明结构,因为dbcc_name的大小取决于dbcc_size(正式声明为char dbcc_name[1](。

根据这个问题,我似乎需要添加

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=255)]

超过dbcc_name.

但是为什么要使用SizeConst=255?我们不知道大小。(从我看到的其他答案来看,似乎没有简单的方法来声明它,以便它知道正确的大小或逐个指定大小的方法。

那么如果我像链接答案中那样设置静态长度会发生什么。如果字符串更短或更长会发生什么?

测试表明,如果它更长,我会得到正确的字符串,如果更短 - 我会得到一个截断的字符串(例如,如果我将 SizeConst 设置为 2 并且真正的字符串是"abc",我会得到"ab"。但是我能确定这就是它的工作原理,还是取决于在这种特定情况下恰好没问题的东西?

你不能完全声明结构,你可以做的是这样的:

[StructLayout(LayoutKind.Sequential)]
private struct _DEV_BROADCAST_DEVICEINTERFACE_A
{
public int dbcc_size;
public uint dbcc_devicetype;
public uint dbcc_reserved;
public Guid dbcc_classguid;
public char dbcc_name; // just for offset; don't use!
}

并像这样使用它:

// get ptr to structure from somewhere (lParam from WM_DEVICECHANGE ...)
IntPtr ptr = ...
// read structure
var iface = Marshal.PtrToStructure<_DEV_BROADCAST_DEVICEINTERFACE_A>(ptr);
// get name pointer
var namePtr = ptr + Marshal.OffsetOf<_DEV_BROADCAST_DEVICEINTERFACE_A>(nameof(_DEV_BROADCAST_DEVICEINTERFACE_A.dbcc_name)).ToInt32();
// get name
var name = Marshal.PtrToStringAnsi(namePtr);

请注意,如果名称可以包含零,则应改为将Marshal.PtrToStringAnsi(namePtr, len)len = dbcc_size - offset of dbcc_name一起使用

相关文章: