NET 2.0代码。
我在struct中编写函数ByteArrayToObject用于插入偏移字节,但是可以快速吗? 计划有很多结构需要附加更改的网络信息。如果我可以将这些字节快速插入到正确的位置,它将作为一个大结构在协议中组织。 感谢您的任何帮助。
在我的情况下,我不喜欢每次都要替换必须执行对象func ObjectToByteArray的所有副本的字节。
/// <summary> Convert an object struct to a byte array </summary>
private static byte[] ObjectToByteArray(Object obj)
{
var size = Marshal.SizeOf(obj);
// Both managed and unmanaged buffers required.
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
// Copy object byte-to-byte to unmanaged memory.
Marshal.StructureToPtr(obj, ptr, false);
// Copy data from unmanaged memory to managed buffer.
Marshal.Copy(ptr, bytes, 0, size);
// Release unmanaged memory.
Marshal.FreeHGlobal(ptr);
return bytes;
}
/// <summary> Need Faster ? </summary>
public static T ByteArrayToObject<T>(ref T obj, int StartOffset, params byte[] bytes)
{
int size = Marshal.SizeOf(obj);
int Length = (bytes.Length > size) ? size : bytes.Length;
byte[] Allbytes = ObjectToByteArray(obj);
Array.Copy(bytes, 0, Allbytes, StartOffset, Length - StartOffset);
var ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(Allbytes, 0, ptr, Length );
obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
Marshal.FreeHGlobal(ptr);
return obj;
}
使用示例
[Serializable]
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
struct Protocol
{
public byte f0;
public byte f1;
public short f2;
public byte f3;
public long f4;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 20000)]
public int[] Array; // 20000
}
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
for (byte i = 1; i < 10; i++)
{
sw.Reset();
sw.Start();
ob = ByteArrayToObject<Protocol>(ref ob,1, i, 0x11, i, 0x22, i);
sw.Stop();
Console.WriteLine("Tick =" + sw.ElapsedTicks);
}
输出
Tick =9940
Tick =686
Tick =593
Tick =474
Tick =562
Tick =5283
Tick =193
Tick =173
Tick =164
答案 0 :(得分:1)
这对评论来说太长了,但要扩展不安全的方法:
unsafe struct Ex
{
public byte f0,f1,f2,f3,f4;
public fixed int buffer[20000];
}
class Program
{
public static unsafe void ByteArrayToEx(Ex* obj, int offset, params byte[] bytes)
{
// you should add some safely nets here sizeof(Ex) should used for size of struct
byte* p = (byte*)obj;
foreach (var b in bytes)
{
p[offset++] = b;
}
// dont return value, it is expensive!
}
unsafe static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
Console.WriteLine(Stopwatch.Frequency);
Ex e = new Ex { f0 = 0, f1 = 1, f2 = 2, f3 = 3, f4 = 4 };
ByteArrayToEx(&e, 2, 5, 6, 7);
for (int i = 0; i < 10; i++) {
sw.Restart();
ByteArrayToEx(&e, 2, (byte) i, 6, 7);
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);
}
}
}
这可能适用于您,也可能不适合您。也不要返回值。您已经在改变指向它的指针。返回这样一个大结构的副本会为每次调用添加10个滴答。
此外,在替补标记时,您需要至少进行一次预热。这就是为什么第一个数字太差了。
我的电脑上的结果:
3312929
4
2
0
0
0
0
0
0
0
0
答案 1 :(得分:0)
重写了一点
public static unsafe void ByteArrayToEx(ref Ex value, int offset, params byte[] bytes)
{
// you should add some safely nets here sizeof(Ex) should used for size of struct
fixed (Ex* obj = &value)
{
byte* p = (byte*)obj;
foreach (var b in bytes)
{
p[offset++] = b;
}
}
// dont return value, it is expensive!
}