C#将结构数组复制到双精度数组
如何将演示数组复制到doubles数组中,而不必通过每个元素执行for(…)?在C++中,我使用MeMCPY,但是在C语言中,我没有找到元帅中需要的东西。C#将结构数组复制到双精度数组,c#,memcpy,value-type,C#,Memcpy,Value Type,如何将演示数组复制到doubles数组中,而不必通过每个元素执行for(…)?在C++中,我使用MeMCPY,但是在C语言中,我没有找到元帅中需要的东西。 [StructLayout(LayoutKind.Sequential)] public struct Demo { double X; double Y; } var data = new Demo[128]; FillWithMeaningfulValues(data); double[] doubles; Co
[StructLayout(LayoutKind.Sequential)]
public struct Demo
{
double X;
double Y;
}
var data = new Demo[128];
FillWithMeaningfulValues(data);
double[] doubles;
Copy(data, out doubles); // ?
void方法不想使用(Demo[]Demo,out double[]double)
{
双精度=新双精度[demo.Length*2];
对于(int i=0,j=0;i
您可以这样做Marshal.Copy
do提供您所需的内容
void MethodIDoNotWantToUse(Demo[] demo, out double[] doubles)
{
doubles = new double[demo.Length * 2];
for(int i = 0, j = 0; i < demo.Length; ++i)
{
doubles[j++] = demo[i].X;
doubles[j++] = demo[i].Y;
}
}
void MethodIWouldPreferToUse(Demo[] demo, out double[] doubles)
{
doubles = new double[demo.Length * 2];
memcopy(doubles, demo, demo.Length * 2 * sizeof(double));
}
由于结构是可blittable的,因此结构的数组是可blittable的。因此,您可以使用
marshall.copy
将struct的数组固定并复制到双数组中
Demo[] array = new Demo[2];
array[0] = new Demo {X = 5.6, Y= 6.6};
array[1] = new Demo {X = 7.6, Y = 8.6};
GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
try
{
IntPtr pointer = handle.AddrOfPinnedObject();
double[] copy = new double[array.Length*2];//This length may be calculated
Marshal.Copy(pointer, copy, 0, copy.Length);
}
finally
{
if (handle.IsAllocated)
handle.Free();
}
您最好将其与希望避免的更简单的
for
循环进行基准测试。for
循环可以完美地执行。可以编写一个通用方法来转换任何兼容类型的数组(所谓“兼容”,我的意思是“元素必须是值类型,并且元素的大小必须兼容”)
可以使用p/Invoke调用Windows API CopyMemory()方法
但是,请记住,这样做可能没有任何性能优势;你应该仔细地计时以确定时间
void CopyDemoArrayToDoubleArray(Demo[] demo, out double[] doubles)
{
doubles = new double[demo.Length * 2];
GCHandle gch = GCHandle.Alloc(demo, GCHandleType.Pinned);
try
{
IntPtr demoPtr = gch.AddrOfPinnedObject();
Marshal.Copy(demoPtr, doubles, 0, doubles.Length);
}
finally
{
gch.Free();
}
}
[DllImport(“kernel32.dll”,EntryPoint=“CopyMemory”,SetLastError=false)]
公共静态外部无效CopyMemory(IntPtr dest、IntPtr src、uint count);
公共TOut[]转换数组(TIn[]输入),其中TIn:struct其中TOut:struct
{
如果(输入==null)
抛出新的ArgumentNullException(“输入”);
int sizeTIn=Marshal.SizeOf(typeof(TIn));
int-sizeTOut=Marshal.SizeOf(typeof(TOut));
int-sizeBytes=input.Length*sizeTIn;
如果((sizeBytes%sizeTOut)!=0)
抛出新ArgumentException(“输入类型的大小与输出类型的大小不兼容”);
int sizeOut=sizeBytes/sizeOut;
var输出=新TOut[sizeOut];
GCHandle inHandle=GCHandle.Alloc(输入,GCHandleType.pinted);
GCHandle outHandle=GCHandle.Alloc(输出,GCHandleType.pinted);
尝试
{
IntPtr inPtr=inHandle.addrofPindedObject();
IntPtr outPtr=outHandle.AddrOfPinnedObject();
CopyMemory(输出端、输入端(uint)大小字节);
}
最后
{
outHandle.Free();
inHandle.Free();
}
返回输出;
}
例如,您可以这样称呼它:
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
public TOut[] ConvertArray<TIn, TOut>(TIn[] input) where TIn:struct where TOut:struct
{
if (input == null)
throw new ArgumentNullException("input");
int sizeTIn = Marshal.SizeOf(typeof(TIn));
int sizeTOut = Marshal.SizeOf(typeof(TOut));
int sizeBytes = input.Length*sizeTIn;
if ((sizeBytes % sizeTOut) != 0)
throw new ArgumentException("Size of input type is not compatible with size of output type.");
int sizeOut = sizeBytes/sizeTOut;
var output = new TOut[sizeOut];
GCHandle inHandle = GCHandle.Alloc(input, GCHandleType.Pinned);
GCHandle outHandle = GCHandle.Alloc(output, GCHandleType.Pinned);
try
{
IntPtr inPtr = inHandle.AddrOfPinnedObject();
IntPtr outPtr = outHandle.AddrOfPinnedObject();
CopyMemory(outPtr, inPtr, (uint)sizeBytes);
}
finally
{
outHandle.Free();
inHandle.Free();
}
return output;
}
Demo[]测试=新的Demo[10];
对于(int i=0;i<10;++i)
测试[i]=新演示{X=i,Y=i};
var结果=转换阵列(测试);
对于(int i=0;i<20;++i)
Console.WriteLine(结果[i]);
您可以使用简单的LINQ查询来获得结果:double[]doubles=data.SelectMany(d=>new[]{d.X,d.Y}).ToArray()代码>@UlugbekUmirov仍然会一个接一个地遍历它们。他试图一次复制整个块。@TimGoodman你是对的,但如果只有128个元素,我看不到大容量复制的性能优势。这只是一个例子。我的真实数据将更大(也更复杂的结构,但仍然只由可blittable类型组成)。我之所以问,是因为我知道C++的方式,却不知道C的方法来实现高效的拷贝。然而,你是对的,在许多情况下,你在评论中的解决方案将是一个完全可行的答案。是的。我使用这种技术在内存中随机播放音频+1.
Demo[] test = new Demo[10];
for (int i = 0; i < 10; ++i)
test[i] = new Demo {X = i, Y = i};
var result = ConvertArray<Demo, double>(test);
for (int i = 0; i < 20; ++i)
Console.WriteLine(result[i]);