我有这个结构定义:
public struct ChangedByte
{
public byte R;
public byte G;
public byte B;
public int x;
public int y;
}
我创建了一个:
List<ChangedByte> testme = new List<ChangedByte>();
(并添加了项目)
我将其转换为数组:
ChangedByte[] alpha = testme.ToArray();
我在SO上找到了类似问题的这个功能:
byte[] StructureToByteArray(object obj)
{
int len = Marshal.SizeOf(obj);
byte[] arr = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, arr, 0, len);
Marshal.FreeHGlobal(ptr);
return arr;
}
我称之为:
byte[] test = StructureToByteArray(alpha);
我收到错误:
类型'new_encoder.Form1 + ChangedByte []'不能作为非托管结构封送;没有有意义的大小或偏移量可以计算出来。
我想将对象列表转换为字节数组(并且可能避免序列化,因为它会增加数组的大小)
可以吗?
附加:
我已经尝试修改过Struct:
public struct ChangedByte
{
[MarshalAs(UnmanagedType.LPWStr)]
public byte R;
[MarshalAs(UnmanagedType.LPWStr)]
public byte G;
[MarshalAs(UnmanagedType.LPWStr)]
public byte B;
[MarshalAs(UnmanagedType.LPWStr)]
public int x;
[MarshalAs(UnmanagedType.LPWStr)]
public int y;
}
但仍然是同样的错误。
答案 0 :(得分:2)
您可以使用以下方法:
static byte[] ArrayToBytes<T>(T[] array) where T : struct
{
IntPtr ptr = IntPtr.Zero;
try
{
int len = Marshal.SizeOf(typeof(T));
int totalLen = array.Length * len;
ptr = Marshal.AllocHGlobal(len);
for (int i = 0; i < array.Length; i++)
{
Marshal.StructureToPtr(array[i], ptr + i * len, false);
}
var bytes = new byte[totalLen];
Marshal.Copy(ptr, bytes, 0, totalLen);
return bytes;
}
finally
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
}
static T[] ArrayFromBytes<T>(byte[] bytes) where T : struct
{
IntPtr ptr = IntPtr.Zero;
try
{
int len = Marshal.SizeOf(typeof(T));
int count = bytes.Length / len;
ptr = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, ptr, bytes.Length);
T[] array = new T[count];
for (int i = 0; i < count; i++)
{
array[i] = Marshal.PtrToStructure<T>(ptr + i * len);
}
return array;
}
finally
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
}
并像这样使用它们:
byte[] test = ArrayToBytes(alpha); // serialize
ChangedByte[] alpha2 = ArrayFromBytes<ChangedByte>(test); // deserialize
答案 1 :(得分:1)
在这种情况下,由于您不仅仅转换结构,而是转换结构数组,因此您需要循环遍历数组并转换每个项目。使用指针算法在缓冲区中移动并添加项目。
public static byte[] StructureArrayToByteArray(ChangedByte[] objs)
{
int structSize = Marshal.SizeOf(typeof(ChangedByte));
int len = objs.Length * structSize;
byte[] arr = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
for (int i = 0; i < objs.Length; i++ ) {
Marshal.StructureToPtr(objs[i], ptr + i*structSize, true);
}
Marshal.Copy(ptr, arr, 0, len);
Marshal.FreeHGlobal(ptr);
return arr;
}