Maison > développement back-end > C++ > Comment convertir efficacement un tableau d'octets C/C en structure C# ?

Comment convertir efficacement un tableau d'octets C/C en structure C# ?

Mary-Kate Olsen
Libérer: 2025-01-19 06:12:11
original
926 Les gens l'ont consulté

How to Efficiently Convert a C/C   Byte Array to a C# Structure?

Lire la structure de données C/C du tableau d'octets vers C#

Question

Cette tâche consiste à convertir un tableau d'octets contenant des données d'une structure C/C en la structure C# correspondante. La structure C/C ressemble à ceci :

<code class="language-c++">typedef struct OldStuff {
    CHAR Name[8];
    UInt32 User;
    CHAR Location[8];
    UInt32 TimeStamp;
    UInt32 Sequence;
    CHAR Tracking[16];
    CHAR Filler[12];
} OldStuff;</code>
Copier après la connexion

La structure C#, nommée NewStuff, est définie comme suit :

<code class="language-csharp">[StructLayout(LayoutKind.Explicit, Size = 56, Pack = 1)]
public struct NewStuff
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    [FieldOffset(0)]
    public string Name;

    [MarshalAs(UnmanagedType.U4)]
    [FieldOffset(8)]
    public uint User;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    [FieldOffset(12)]
    public string Location;

    [MarshalAs(UnmanagedType.U4)]
    [FieldOffset(20)]
    public uint TimeStamp;

    [MarshalAs(UnmanagedType.U4)]
    [FieldOffset(24)]
    public uint Sequence;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    [FieldOffset(28)]
    public string Tracking;
}</code>
Copier après la connexion

Solution proposée

Dans un premier temps, une approche plus lourde a été envisagée, impliquant une mémoire épinglée et utilisant Marshal.PtrToStructure :

<code class="language-csharp">int BufferSize = Marshal.SizeOf(typeof(NewStuff));
byte[] buff = new byte[BufferSize];

Array.Copy(SomeByteArray, 0, buff, 0, BufferSize);

handle = GCHandle.Alloc(buff, GCHandleType.Pinned);

MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));

handle.Free();</code>
Copier après la connexion

Améliorations

Après une analyse plus approfondie, il a été déterminé que la copie tampon dans la méthode d'origine n'était pas nécessaire. Au lieu de cela, l’épinglage direct de la poignée est suffisant :

<code class="language-csharp">GCHandle handle;
NewStuff MyStuff;

handle = GCHandle.Alloc(SomeByteArray, GCHandleType.Pinned);
try
{
    MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));
}
finally
{
    handle.Free();
}</code>
Copier après la connexion

En outre, une version encore plus simple peut être utilisée en utilisant des génériques (nécessite une commutation non sécurisée) :

  • Générique :
<code class="language-csharp">T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
    T stuff;
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try
    {
        stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    }
    finally
    {
        handle.Free();
    }
    return stuff;
}</code>
Copier après la connexion
  • Plus facile (dangereux) :
<code class="language-csharp">unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
    fixed (byte* ptr = &bytes[0])
    {
        return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T));
    }
}</code>
Copier après la connexion

Utilisez BinaryReader pour améliorer les performances

Bien que la solution préférée implique la fixation et Marshal.PtrToStructure, dans certains cas, l'analyse des données à l'aide de la classe BinaryReader peut offrir des avantages en termes de performances. Cependant, des mises en œuvre spécifiques doivent être évaluées pour déterminer si ces gains sont significatifs.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal