C#调用C++ memcpy实现各种参数类型的内存拷贝 VS marshal.copy的实现 效率对比


using System; using System.Runtime.InteropServices; using System.IO; namespace tx { struct ST { public char c1; public int x; public int y; } class Ct { [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] public static extern void MemCopy(byte[] dest, byte[] src, int count);//字节数组到字节数组的拷贝  [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] public static extern void MemCopy(int[] dest, byte[] src, int count);//字节数组到整形数组的拷贝  [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] public unsafe static extern void MemCopy(ref ST dest, byte[] src, int count);//注意只有结构体能这么做,class不可以 static void Main(string[] args) { //测试---------------------------------------------- var ms = new MemoryStream(); BinaryWriter writer = new BinaryWriter(ms); writer.Write((byte)'a'); writer.Write((byte)'b'); writer.Write((byte)'c'); writer.Write((byte)'d'); writer.Write((Int32)10); writer.Write((Int32)30); var len = ms.Length; int[] bs = new int[len/4]; byte[] bss = new byte[len]; byte[] buf = ms.GetBuffer(); var ot = new ST(); MemCopy(bs, buf, (int)len); MemCopy(bss, buf, (int)len); MemCopy(ref ot, buf, (int)len);//注意只有结构体能这么做,class不可以  } } }

Marshal对应的实现ByteToStruct,及效率对比完整程序如下:以读取魔兽世界M2文件为例,经测试发现ByteToStruct用时为MemCopy的3倍到4倍

using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using NUnit.Framework.Internal.Filters; using System; using System.Runtime.InteropServices; using System.Diagnostics; using Debug = UnityEngine.Debug; using System.Threading; using System.ComponentModel; struct Sphere { /*0x00*/public float xmin, ymin, zmin; /*0x0C*/public float xmax, ymax, zmax; /*0x18*/public float radius; }; struct ModelHeader { public byte id0, id1, id2, id3; public byte ver0, ver1, ver2, ver3; public UInt32 nameLength; public UInt32 nameOfs; public UInt32 GlobalModelFlags; // 1: tilt x, 2: tilt y, 4:, 8: add another field in header, 16: ; (no other flags as of 3.1.1); public UInt32 nGlobalSequences; // AnimationRelated public UInt32 ofsGlobalSequences; // A list of timestamps. public UInt32 nAnimations; // AnimationRelated public UInt32 ofsAnimations; // Information about the animations in the model. public UInt32 nAnimationLookup; // AnimationRelated public UInt32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block. //UInt32 nD; //UInt32 ofsD; public UInt32 nBones; // BonesAndLookups public UInt32 ofsBones; // Information about the bones in this model. public UInt32 nKeyBoneLookup; // BonesAndLookups public UInt32 ofsKeyBoneLookup; // Lookup table for key skeletal bones. public UInt32 nVertices; // GeometryAndRendering public UInt32 ofsVertices; // Vertices of the model. public UInt32 nViews; // GeometryAndRendering //UInt32 ofsViews; // Views (LOD) are now in .skins. public UInt32 nColors; // ColorsAndTransparency public UInt32 ofsColors; // Color definitions. public UInt32 nTextures; // TextureAndTheifAnimation public UInt32 ofsTextures; // Textures of this model. public UInt32 nTransparency; // H, ColorsAndTransparency public UInt32 ofsTransparency; // Transparency of textures. //UInt32 nI; // always unused ? //UInt32 ofsI; public UInt32 nTexAnims; // J, TextureAndTheifAnimation public UInt32 ofsTexAnims; public UInt32 nTexReplace; // TextureAndTheifAnimation public UInt32 ofsTexReplace; // Replaceable Textures. public UInt32 nTexFlags; // Render Flags public UInt32 ofsTexFlags; // Blending modes / render flags. public UInt32 nBoneLookup; // BonesAndLookups public UInt32 ofsBoneLookup; // A bone lookup table. public UInt32 nTexLookup; // TextureAndTheifAnimation public UInt32 ofsTexLookup; // The same for textures. public UInt32 nTexUnitLookup; // L, TextureAndTheifAnimation, seems gone after Cataclysm public UInt32 ofsTexUnitLookup; // And texture units. Somewhere they have to be too. public UInt32 nTransparencyLookup; // M, ColorsAndTransparency public UInt32 ofsTransparencyLookup; // Everything needs its lookup. Here are the transparencies. public UInt32 nTexAnimLookup; // TextureAndTheifAnimation public UInt32 ofsTexAnimLookup; // Wait. Do we have animated Textures? Wasn't ofsTexAnims deleted? oO public Sphere collisionSphere; public Sphere boundSphere; public UInt32 nBoundingTriangles; // Miscellaneous public UInt32 ofsBoundingTriangles; public UInt32 nBoundingVertices; // Miscellaneous public UInt32 ofsBoundingVertices; public UInt32 nBoundingNormals; // Miscellaneous public UInt32 ofsBoundingNormals; public UInt32 nAttachments; // O, Miscellaneous public UInt32 ofsAttachments; // Attachments are for weapons etc. public UInt32 nAttachLookup; // P, Miscellaneous public UInt32 ofsAttachLookup; // Of course with a lookup. public UInt32 nEvents; //  public UInt32 ofsEvents; // Used for playing sounds when dying and a lot else. public UInt32 nLights; // R public UInt32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too. public UInt32 nCameras; // S, Miscellaneous public UInt32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab. public UInt32 nCameraLookup; // Miscellaneous public UInt32 ofsCameraLookup; // And lookup-time again, unit16 public UInt32 nRibbonEmitters; // U, Effects public UInt32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails. public UInt32 nParticleEmitters; // V, Effects public UInt32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles. public UInt32 nUnknown; // Apparently added in models with the 8-flag only. If that flag is not set, this field does not exist! public UInt32 ofsUnknown; // An array of shorts, related to renderflags. }; public class m2 : MonoBehaviour { [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] public static extern void MemCopy(byte[] dest, byte[] src, int count);//字节数组到字节数组的拷贝  [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] public static extern void MemCopy(int[] dest, byte[] src, int count);//字节数组到整形数组的拷贝  [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] static extern void MemCopy(ref ModelHeader dest, byte[] src, int count);//注意只有结构体能这么做,class不可以 // Use this for initialization void Start () { LoadMesh ("Assets/models/creature/arcticcondor.m2"); } // Update is called once per frame void Update () { } #region public public UInt32[] globalSequences; #endregion #region private void LoadMesh(string filePath){ if(false == File.Exists(filePath)){ Debug.LogError ("file not exist : " + filePath); return; } var bytes = File.ReadAllBytes (filePath); var buffer = new BufferedStream (new MemoryStream (bytes)); var wt = new Stopwatch (); wt.Start (); var theader = new ModelHeader (); var size_header = Marshal.SizeOf (theader); MemCopy (ref theader, bytes, size_header); Debug.Log ("MemCopy------------------------" + wt.Elapsed); wt.Stop (); var wt2 = new Stopwatch (); wt2.Start (); var header = (ModelHeader)ByteToStruct (bytes, typeof(ModelHeader)); Debug.Log ("ByteToStruct------------------------" + wt2.Elapsed); wt2.Stop (); if(header.id0 != 'M' || header.id1 != 'D' || header.id2 != '2' || header.id3 != '0' ){ Debug.LogError ("read m2 header : invalid id0, id1, id2, id3"); return; } if(header.nameOfs != 304 && header.nameOfs != 320){ Debug.LogError ("Invalid model nameOfs=" + header.nameOfs); return; } // Error check // 10 1 0 0 = WoW 5.0 models (as of 15464) // 10 1 0 0 = WoW 4.0.0.12319 models // 9 1 0 0 = WoW 4.0 models // 8 1 0 0 = WoW 3.0 models // 4 1 0 0 = WoW 2.0 models // 0 1 0 0 = WoW 1.0 models if(bytes.Length < header.ofsParticleEmitters){ Debug.LogError ("unable to load the model \"" + filePath); return; } if(header.nGlobalSequences > 0){ globalSequences = new UInt32[header.nGlobalSequences]; } } void RenderMesh(){ } public static object ByteToStruct(byte[] bytes, Type type) { int size = Marshal.SizeOf(type); if (size > bytes.Length) { return null; } //分配结构体内存空间 IntPtr structPtr = Marshal.AllocHGlobal(size); //将byte数组拷贝到分配好的内存空间 Marshal.Copy(bytes, 0, structPtr, size); //将内存空间转换为目标结构体 object obj = Marshal.PtrToStructure(structPtr, type); //释放内存空间  Marshal.FreeHGlobal(structPtr); return obj; } #endregion }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM