首先,我是C#的全新(如在1-2周内)。我正在尝试将WinDivert方法包装在C#中使用,并且我一直在混合成功和失败。虽然我不确定,但我相信我已经把这个问题缩小到一个错位(字面上),在非托管代码中如何定义某些结构以及如何在C#中定义它们,因为(据我所知)a C#的限制。
来自https://github.com/basil00/Divert/blob/master/include/windivert.h
的示例typedef struct
{
UINT8 HdrLength:4;
UINT8 Version:4;
UINT8 TOS;
UINT16 Length;
UINT16 Id;
UINT16 FragOff0;
UINT8 TTL;
UINT8 Protocol;
UINT16 Checksum;
UINT32 SrcAddr;
UINT32 DstAddr;
} WINDIVERT_IPHDR, *PWINDIVERT_IPHDR;
这是我遇到问题翻译的结构之一。如您所见,HdrLength和Version被定义为每个占用4位结构。在C#版本中,我尝试简单地声明字节HdrLengthAndVersion,我尝试将布局更改为明确,并手动定义成员的位置,以便它们在这样的情况下重叠,以确保相同的内存长度和位置等。一些其他更大的结构变得特别复杂。
我很好奇是否有任何方法可以正确地将其转换为C#?我也很好奇这是否可能,或者它是否会成为不同架构的问题。我知道我们正在进入内存对齐,填充等,我承认这是一个主题,我不是专家,这就是为什么我在这里:)。
作为第二种选择,我正在考虑只做一些无效指针(因为托管的东西分配并使用这些对象)并且只是移动位置然后键入将指针转换回我实际需要访问的特定值。但同样,不确定这是否可能。
也只是为了提及,我尝试过SWIG。没有用,我在尝试使用它时遇到了998个ERROR_NOACCESS错误,所以,只是一大堆类,我没有写出更多的问题。
答案 0 :(得分:3)
由于FieldOffsetAttribute
接受以字节为单位的偏移量,您可以将HdrLength
和Version
的偏移量设置为0
,并添加将返回正确值的辅助属性每个字段使用位移。
例如:
[StructLayout(LayoutKind.Explicit)]
struct WINDIVERT_IPHDR
{
[FieldOffset(0)]
private byte hdrLength;
[FieldOffset(0)]
private byte version;
[FieldOffset(1)]
private byte tos;
...
public byte HdrLength
{
get { return (byte)(hdrLength & 0xF); }
}
public byte Version
{
get { return (byte)(version >> 4); }
}
public byte TOS { get { return tos; } }
...
}
请注意,由于您使用的是LayoutKind.Explicit
,因此您必须为所有结构字段定义FieldOffset
。