问题描述
我下面提供的PInvoke code here但我在变长数组为size = 1的编组略有惊,然后通过它步进通过计算偏移,而不是索引到一个数组。是不是有更好的办法?如果没有的话,我应该怎么做,使之安全的32位和64位?
I'm following the pinvoke code provided here but am slightly scared by the marshalling of the variable-length array as size=1 and then stepping through it by calculating an offset instead of indexing into an array. Isn't there a better way? And if not, how should I do this to make it safe for 32-bit and 64-bit?
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public uint Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_GROUPS
{
public int GroupCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public SID_AND_ATTRIBUTES[] Groups;
};
public void SomeMethod()
{
IntPtr tokenInformation;
// ...
string retVal = string.Empty;
TOKEN_GROUPS groups = (TOKEN_GROUPS)Marshal.PtrToStructure(tokenInformation, typeof(TOKEN_GROUPS));
int sidAndAttrSize = Marshal.SizeOf(new SID_AND_ATTRIBUTES());
for (int i = 0; i < groups.GroupCount; i++)
{
// *** Scary line here:
SID_AND_ATTRIBUTES sidAndAttributes = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(
new IntPtr(tokenInformation.ToInt64() + i * sidAndAttrSize + IntPtr.Size),
typeof(SID_AND_ATTRIBUTES));
// ...
}
我看<一href="http://stackoverflow.com/questions/3338297/managed-to-unmanaged-$c$c-call-causes-access-violation-sometimes">here宣布数组的长度一样多大于它很可能是,但似乎有其自身的问题的另一种方法。
I see here another approach of declaring the length of the array as much bigger than it's likely to be, but that seemed to have its own problems.
作为一个方面的问题:当我通过上面的code在调试步骤,我无法评价 tokenInformation.ToInt64()
或 ToInt32()
。我得到一个ArgumentOutOfRangeException。但是,code行执行就好了!?这是怎么回事吗?
As a side question: When I step through the above code in the debugger I'm not able to evaluate tokenInformation.ToInt64()
or ToInt32()
. I get an ArgumentOutOfRangeException. But the line of code executes just fine!? What's going on here?
推荐答案
我认为它看起来还行 - 作为没关系,任何非托管的土地戳的是,反正
I think it looks okay -- as okay as any poking about in unmanaged land is, anyway.
不过,我不知道为什么一开始是 tokenInformation.ToInt64()+ IntPtr.Size
,而不是 tokenInformation.ToInt64()+ 4
(作为GroupCount字段类型是int,而不是IntPtr的)。这是包装的结构/对齐或只是有鬼?我不知道在这里。
However, I wonder why the start is tokenInformation.ToInt64() + IntPtr.Size
and not tokenInformation.ToInt64() + 4
(as the GroupCount field type is an int and not IntPtr). Is this for packing/alignment of the structure or just something fishy? I do not know here.
使用 tokenInformation.ToInt64()
是很重要的,因为在64位机的会爆炸的(发生OverflowException)如果IntPtr的值大于什么int可以存储。但是,CLR将处理长就好在这两种体系结构,它并不会改变从提取的IntPtr(因此实际值放回新的IntPtr(...)
)。
Using tokenInformation.ToInt64()
is important because on a 64-bit machine will explode (OverflowException) if the IntPtr value is larger than what an int can store. However, the CLR will handle a long just fine on both architectures and it doesn't change the actual value extracted from the IntPtr (and thus put back into the new IntPtr(...)
).
想象这样(未经测试)功能,以方便包装:
Imagine this (untested) function as a convenience wrapper:
// unpacks an array of structures from unmanaged memory
// arr.Length is the number of items to unpack. don't overrun.
void PtrToStructureArray<T>(T[] arr, IntPtr start, int stride) {
long ptr = start.ToInt64();
for (int i = 0; i < arr.Length; i++, ptr += stride) {
arr[i] = (T)Marshal.PtrToStructure(new IntPtr(ptr), typeof(T));
}
}
var attributes = new SID_AND_ATTRIBUTES[groups.GroupCount];
PtrToStructureArray(attributes, new IntPtr(tokenInformation.ToInt64() + IntPtr.Size), sidAndAttrSize);
快乐编码。
这篇关于如何PInvoke的结构从GetTokenInformation(可变长度数组)安全地用于32位和64位? C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!