Ror*_*ory 5 .net c# pinvoke marshalling
我正在遵循此处提供的 pinvoke 代码,但对将可变长度数组编组为 size=1 然后通过计算偏移量而不是索引到数组来逐步执行它感到有点害怕。难道就没有更好的办法吗?如果不是,我应该如何做才能确保 32 位和 64 位安全?
[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));
// ...
}
Run Code Online (Sandbox Code Playgroud)
我在这里看到另一种方法,将数组的长度声明为比可能的长度大得多,但这似乎有其自身的问题。
作为一个附带问题:当我在调试器中单步执行上述代码时,我无法评估tokenInformation.ToInt64()or ToInt32()。我收到 ArgumentOutOfRangeException。但是这行代码执行得很好!?这里发生了什么?
小智 2
我认为这看起来还不错——无论如何,就像在无人管理的土地上闲逛一样。
但是,我想知道为什么 start 是tokenInformation.ToInt64() + IntPtr.Size而不是tokenInformation.ToInt64() + 4(因为 GroupCount 字段类型是 int 而不是 IntPtr)。这是为了结构的包装/对齐还是只是一些可疑的东西?我不知道这里。
使用tokenInformation.ToInt64()很重要,因为在 64 位计算机上,如果 IntPtr 值大于 int 可以存储的值,则会发生爆炸(OverflowException)。但是,CLR 在两种体系结构上都能很好地处理 long,并且不会更改从 IntPtr 中提取的实际值(并因此放回new IntPtr(...))。
想象一下这个(未经测试的)函数作为一个方便的包装器:
// 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);
Run Code Online (Sandbox Code Playgroud)
快乐编码。
| 归档时间: |
|
| 查看次数: |
2155 次 |
| 最近记录: |