2015-08-11 2 views
5

Si vous voulez faire une copie de la mémoire entre les deux tableaux, il y a une fonction Array.Copy pour que .NET:Existe-t-il un moyen portable de copier un bloc de mémoire en C#?

char[] GetCopy(char[] buf) 
{ 
    char[] result = new char[buf.Length]; 
    Array.Copy(buf, result); 
    return result; 
} 

Ceci est généralement plus rapide que manuellement-boucle pour copier tous les personnages buf à result, parce que c'est une opération de copie de bloc qui prend simplement un morceau de mémoire et l'écrit à la destination.

De même, si on me donnait à la place un char* et un int en précisant sa taille, quelles sont mes options? Voici ceux que j'ai pris en compte:

  • Buffer.BlockCopy: nécessite src et dst être des tableaux
  • Buffer.MemoryCopy: exactement ce que je cherche, mais seulement disponible sur. NET bureau
  • Marshal.Copy: cessé d'être pris en charge dans la version 2.0
  • .NET

Ou, s'il n'y a pas alter natif, existe-t-il un moyen de construire un tableau à partir d'un pointeur char* et d'une longueur int? Si je pouvais le faire, je pourrais juste convertir les pointeurs en tableaux et les passer dans Array.Copy.

Je ne cherche pas de boucles car, comme je l'ai dit, elles ne sont pas très efficaces par rapport aux copies de blocs, mais si c'est la seule façon que je devrais faire. Je recherche essentiellement memcpy(), mais en C# et peut être utilisé dans les PCL.

+0

Avez-vous réellement mesuré la quantité de copie de mémoire manuelle de base plus lente et moins sûre (similaire à [Buffer.MemoryCopy]) (http://referencesource.microsoft.com/#mscorlib/system/buffer.cs,c2ca91c0d34a8f86))? Comme il n'y a pas de vérification de l'exécution et que le code résultant est minuscule, il ne devrait pas y avoir beaucoup de différence par rapport aux opérations de déplacement de blocs (et vraiment 'memcpy' est souvent juste une boucle manuelle). –

+0

@AlexeiLevenkov Non, mais ne devrait-il pas être plus rapide? Je ne pose pas cette question parce que je suis insatisfait de la mise en boucle manuelle; Je suis juste curieux de savoir s'il y a un meilleur moyen. –

+1

Je n'en ai aucune idée, mais puisque la mémoire de copie est limitée par la vitesse de la mémoire et le processeur, je ne m'attendrais pas à ce que la boucle manuelle soit plus lente que la copie de bloc spécifique à l'unité centrale. Notez par la façon dont post demande l'équivalent de 'memcpy' qui ne compile pas nécessairement en instructions de copie de bloc ... Pensez à faire votre propre benchmark. Vous pouvez trouver plus d'informations sur la copie dans des questions similaires comme http://stackoverflow.com/questions/2658380/how-can-i-copy-unmanaged-data-in-c-sharp-and-how-fast-is-it et http://stackoverflow.com/questions/4707012/c-memcpy-vs-stdcopy). –

Répondre

2

Vous indiquez que Marshal.Copy ne serait plus supporté, mais sur la documentation de la classe Marshal je ne trouve aucune indication à ce sujet.

Bien au contraire, la classe est disponible pour les versions générales suivantes: 4.6, 4.5, 4, 3.5, 3.0, 2.0, 1.1

Une mise en oeuvre possible d'une fonction d'utilité à partir de cette méthode serait:

public static void CopyFromPtrToPtr(IntPtr src, uint srcLen, 
            IntPtr dst, uint dstLen) 
{ 
    var buffer = new byte[srcLen]; 
    Marshal.Copy(src, buffer, 0, buffer.Length); 
    Marshal.Copy(buffer, 0, dst, (int)Math.Min(buffer.Length, dstLen)); 
} 

Cependant, il est tout à fait possible que la copie des octets de IntPtr à byte[] et retour annule tout gain possible de performances par rapport épinglant la mémoire dangereuse et la copie dans une boucle.

En fonction de la portabilité du code, vous pouvez également utiliser P/Invoke pour utiliser réellement la méthode memcpy. Cela devrait fonctionner correctement sur Windows 2000 et versions ultérieures (tous les systèmes sur lesquels Microsoft Visual C Run-Time Library est installé). Edit: La deuxième approche ne serait pas adaptée aux bibliothèques de classes portables, la première serait cependant.

1

Je ne me souviens pas des API intégrées de la BCL, mais vous pouvez copier le code BCL memcpy et l'utiliser. Utilisez Reflector et recherchez "memcpy" pour le trouver.Le code dangereux est parfaitement défini et portable.