Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果结构中的字符串比所使用的p/Invoked签名长或短,会发生什么情况?_C#_C++_C_.net_Pinvoke - Fatal编程技术网

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

C# 如果结构中的字符串比所使用的p/Invoked签名长或短,会发生什么情况?,c#,c++,c,.net,pinvoke,C#,C++,C,.net,Pinvoke,举个例子,我想使用from C#。但是,我不确定如何声明该结构,因为dbcc\u name的大小取决于dbcc\u size(正式声明为char dbcc\u name[1]) 据我所知,似乎我需要补充 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=255)] 超过dbcc\u name 但是为什么要使用SizeConst=255?我们不知道尺寸。(从我看到的其他答案来看,这似乎是一种逐案指定大小的方法。) 那么,如果我在链接答案中设置一个静态长度

举个例子,我想使用from C#。但是,我不确定如何声明该结构,因为
dbcc\u name
的大小取决于
dbcc\u size
(正式声明为
char dbcc\u name[1]

据我所知,似乎我需要补充

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=255)]
超过
dbcc\u 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);
然后像这样使用它:

[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);
//从某处获取ptr到结构(来自WM_DEVICECHANGE的LPRAM…)
IntPtr ptr=。。。
//读结构
var iface=Marshal.ptr结构(ptr);
//获取名称指针
var namePtr=ptr+Marshal.OffsetOf(nameof(_DEV_BROADCAST_DEVICEINTERFACE_A.dbcc_name)).ToInt32();
//得名
var name=Marshal.PtrToStringAnsi(namePtr);

注意:如果名称可以包含零,则应使用
Marshal.PtrToStringAnsi(namePtr,len)
len=dbcc_size-dbcc_name的偏移量

即使使用较少的内存,也需要保留最大内存大小。c#中有一个属性,即结构的分配大小,如果超过该大小,则在运行代码时会出现异常。如果不添加行,则不会出现编译器错误。@jdweng请参阅我的编辑(-问题的最后一段)-似乎设置一个较大的大小就可以了。但我不知道它是否总是能正常工作。这取决于一个字符是一个字节还是两个字节。如果是两个字节,则需要511而不是255。看起来是一个c#双字节字符,所以需要511。见平沃克:@jdweng见我的另一个问题
dbcc_name
既不是字符,也不是指针。它只是字符串的第一个字符。它是一个窗口结构,必须满足windows的要求。谢谢。我会调查的。(我更新了我的问题,就在你发布答案的时候。请看我问题的最后一段-似乎我可以简单地设置一个高的数字,而且效果很好。但我不知道它是否总是很好。)你似乎在考虑
dbcc\u name
一个指针。从文档(在我的问题中链接)和它似乎不是。@ispiro-这不是我正在考虑的。如果您在_DEV_BROADCAST_DEVICEINTERFACE_a结构上有一个指针,那么您可以计算dbcc_name(=>namePtr)上的指针,因此我们计算指向字符串开头的指针,然后读取所有指针(直到一个空字符)。现在我明白了。谢谢你的毅力。我假设我们也可以使用另一个重载并使用
dbcc_size
来计算要读取多少。再次感谢。我知道你的代码应该是有效的。但是现在尝试一下,我只得到了
dbcc\u name
的第一个字符。我想我会试试另一种超负荷。。。