嗨,我正在尝试将C / C++ Strcut转换为C#,以及如何用C#中另一个结构的地址填充结构成员?
C / C++结构看起来像:
typedef struct _NDISUIO_QUERY_OID
{
NDIS_OID Oid;
PTCHAR ptcDeviceName;
UCHAR Data[sizeof(ULONG)];
} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID;
typedef struct My_Struct
{
//les have 2 variables...
UINT a;
UINT b;
}My_STATS, *PMy_STATS;
PNDISUIO_QUERY_OID pQueryOid = NULL;
pQueryOid = (PNDISUIO_QUERY_OID)malloc(sizeof(NDISUIO_QUERY_OID)+ sizeof(My_STATS)) ;
PMy_STATS Statistics;
pQueryOid->Oid = ulOIDCode;//Required OID
pQueryOid->ptcDeviceName = AUB_NAME;//REquired STRING
memcpy(pQueryOid->Data, Statistics, sizeof(My_STATS));
我的C#结构是:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct _NDISUIO_QUERY_OID
{
public uint Oid;
[MarshalAs(UnmanagedType.LPWStr)]
public string ptcDeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = sizeof(uint))]
public string Data;
};
问题:如何在C#中将统计信息结构复制到数据数组?
谢谢 :)
最佳答案
这是我的实现(仅供引用,SDF包含所有这些代码以及更多内容)
internal class NDISQueryOid
{
protected const int NDISUIO_QUERY_OID_SIZE = 12;
protected byte[] m_data;
public int Size { get; private set; }
public NDISQueryOid(byte[] data)
{
int extrasize = data.Length;
Size = 8 + extrasize;
m_data = new byte[Size];
Buffer.BlockCopy(data, 0, m_data, DataOffset, data.Length);
}
public NDISQueryOid(int extrasize)
{
Size = NDISUIO_QUERY_OID_SIZE + extrasize;
m_data = new byte[Size];
}
protected const int OidOffset = 0;
public uint Oid
{
get { return BitConverter.ToUInt32(m_data, OidOffset); }
set
{
byte[] bytes = BitConverter.GetBytes(value);
Buffer.BlockCopy(bytes, 0, m_data, OidOffset, 4);
}
}
protected const int ptcDeviceNameOffset = OidOffset + 4;
public unsafe byte* ptcDeviceName
{
get
{
return (byte*)BitConverter.ToUInt32(m_data, ptcDeviceNameOffset);
}
set
{
byte[] bytes = BitConverter.GetBytes((UInt32)value);
Buffer.BlockCopy(bytes, 0, m_data, ptcDeviceNameOffset, 4);
}
}
protected const int DataOffset = ptcDeviceNameOffset + 4;
public byte[] Data
{
get
{
byte[] b = new byte[Size - DataOffset];
Array.Copy(m_data, DataOffset, b, 0, Size - DataOffset);
return b;
}
set
{
Size = 8 + value.Length;
m_data = new byte[Size];
Buffer.BlockCopy(value, 0, m_data, DataOffset, value.Length);
}
}
public byte[] getBytes()
{
return m_data;
}
public static implicit operator byte[](NDISQueryOid qoid)
{
return qoid.m_data;
}
}
请注意,在我的用法中,NDIS IOCT接收了一个指针(我的大多数NDIS工作都是不安全的),因此您必须在此处进行一些调整。
因此,例如,如果您要查询BSSID,我知道BSSID数据是36个字节,因此我将创建如下内容:
var queryOID = new NDISQueryOid(36);
然后分配名称并调用NDIS(生产代码比这更多的检查):
byte[] nameBytes = System.Text.Encoding.Unicode.GetBytes(adapterName + '\0');
fixed (byte* pName = &nameBytes[0])
{
queryOID.ptcDeviceName = pName;
queryOID.Oid = (uint)oid;
var bytes = queryOID.getBytes();
ndis.DeviceIoControl(IOCTL_NDISUIO_QUERY_OID_VALUE, bytes, bytes);
var result = new byte[queryOID.Data.Length];
Buffer.BlockCopy(queryOID.Data, 0, result, 0, result.Length);
}
编辑
因此,上面的
result
成员是查询“结果”的字节数组。它的含义和解释方式取决于您查询的OID是什么。例如,如果您要查询当前连接的SSID(即NDIS_OID.SSID
),那么它将以4个字节的长度返回,后跟ASCII编码的名称,因此您可以这样解密:int len = BitConverter.ToInt32(data, 0);
if (len > 0)
{
ssid = System.Text.Encoding.ASCII.GetString(data, 4, len);
}
但是同样,这仅适用于一个特定的OID。您必须为您决定支持的每个传入OID处理所有退货情况。
关于c# - 如何使用以下任务在C#.Net CF中执行memcpy,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22604111/