C # veri yapıları Haritalama Akış verileri

oy
20

bir veri yapısı veya tersi için bir akım ya da dizi ile toplanarak eşleme veri yolu var mı? C ++ bu sadece içinde (geri ya da tersi), örneğin kullanmak isteyen bir veri türü gibi akım için bir işaretçi döküm meselesi olacaktır: C ++

Mystruct * pMyStrct = (Mystruct*)&SomeDataStream;
pMyStrct->Item1 = 25;

int iReadData = pMyStrct->Item2;

Açıkçası C ++ yolu gelen verileri okurken akış verilerinin kalitesinin emin olmadıkça oldukça güvensiz, ancak giden veriler için süper hızlı ve kolaydır.

Oluştur 05/08/2008 saat 14:11
kaynak kullanıcı
Diğer dillerde...                            


4 cevaplar

oy
16

Çoğu insan (daha hızlı ikili ve daha yavaş XML biçimlendirici vardır, ikisi de yansıması bağlıdır ve belirli bir dereceye kadar toleranslı versiyonu olan) .NET seri kullanmak

Ancak, en hızlı (güvensiz) yolu istiyorsanız - neden olmasın:

Yazı:

YourStruct o = new YourStruct();
byte[] buffer = new byte[Marshal.SizeOf(typeof(YourStruct))];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(o, handle.AddrOfPinnedObject(), false);
handle.Free();

Okuma:

handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
o = (YourStruct)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(YourStruct));
handle.Free();
Cevap 05/08/2008 saat 16:46
kaynak kullanıcı

oy
5

Vaka LUBOS yılında HASKO cevabı yeterince güvensiz değildi, orada da gerçekten C # işaretçileri kullanarak, güvenli bir yöntem. İşte yaşamanıza bazı ipuçları ve tuzaklar var:

using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;

// Use LayoutKind.Sequential to prevent the CLR from reordering your fields.
[StructLayout(LayoutKind.Sequential)]
unsafe struct MeshDesc
{
    public byte NameLen;
    // Here fixed means store the array by value, like in C,
    // though C# exposes access to Name as a char*.
    // fixed also requires 'unsafe' on the struct definition.
    public fixed char Name[16];
    // You can include other structs like in C as well.
    public Matrix Transform;
    public uint VertexCount;
    // But not both, you can't store an array of structs.
    //public fixed Vector Vertices[512];
}

[StructLayout(LayoutKind.Sequential)]
unsafe struct Matrix
{
    public fixed float M[16];
}

// This is how you do unions
[StructLayout(LayoutKind.Explicit)]
unsafe struct Vector
{
    [FieldOffset(0)]
    public fixed float Items[16];
    [FieldOffset(0)]
    public float X;
    [FieldOffset(4)]
    public float Y;
    [FieldOffset(8)]
    public float Z;
}

class Program
{
    unsafe static void Main(string[] args)
    {
        var mesh = new MeshDesc();
        var buffer = new byte[Marshal.SizeOf(mesh)];

        // Set where NameLen will be read from.
        buffer[0] = 12;
        // Use Buffer.BlockCopy to raw copy data across arrays of primitives.
        // Note we copy to offset 2 here: char's have alignment of 2, so there is
        // a padding byte after NameLen: just like in C.
        Buffer.BlockCopy("Hello!".ToCharArray(), 0, buffer, 2, 12);

        // Copy data to struct
        Read(buffer, out mesh);

        // Print the Name we wrote above:
        var name = new char[mesh.NameLen];
        // Use Marsal.Copy to copy between arrays and pointers to arrays.
        unsafe { Marshal.Copy((IntPtr)mesh.Name, name, 0, mesh.NameLen); }
        // Note you can also use the String.String(char*) overloads
        Console.WriteLine("Name: " + new string(name));

        // If Erik Myers likes it...
        mesh.VertexCount = 4711;

        // Copy data from struct:
        // MeshDesc is a struct, and is on the stack, so it's
        // memory is effectively pinned by the stack pointer.
        // This means '&' is sufficient to get a pointer.
        Write(&mesh, buffer);

        // Watch for alignment again, and note you have endianess to worry about...
        int vc = buffer[100] | (buffer[101] << 8) | (buffer[102] << 16) | (buffer[103] << 24);
        Console.WriteLine("VertexCount = " + vc);
    }

    unsafe static void Write(MeshDesc* pMesh, byte[] buffer)
    {
        // But byte[] is on the heap, and therefore needs
        // to be flagged as pinned so the GC won't try to move it
        // from under you - this can be done most efficiently with
        // 'fixed', but can also be done with GCHandleType.Pinned.
        fixed (byte* pBuffer = buffer)
            *(MeshDesc*)pBuffer = *pMesh;
    }

    unsafe static void Read(byte[] buffer, out MeshDesc mesh)
    {
        fixed (byte* pBuffer = buffer)
            mesh = *(MeshDesc*)pBuffer;
    }
}
Cevap 24/10/2009 saat 12:37
kaynak kullanıcı

oy
2

elle her üye değişkeni doldurmak gerekiyorsa kadarıyla ilkel sırayla bir nesne ile ilişkili değişken tiplerinin listesini almak için FormatterServices kullanılarak söz konusu olduğunda bunu biraz genelleme yapabiliriz. Ben akışı geliyor farklı mesaj türlerinin bir sürü vardı bir projede bunu yapmak yaşadım ve kesinlikle her mesaj için seri hale / deserializer yazmak istemedim.

Burada bir byte [] dan deserialization genelleme için kullanılan kod.

public virtual bool SetMessageBytes(byte[] message)
    {
        MemberInfo[] members = FormatterServices.GetSerializableMembers(this.GetType());
        object[] values = FormatterServices.GetObjectData(this, members);
        int j = 0;

        for (int i = 0; i < members.Length; i++)
        {
            string[] var = members[i].ToString().Split(new char[] { ' ' });
            switch (var[0])
            {
                case "UInt32":
                    values[i] = (UInt32)((message[j] << 24) + (message[j + 1] << 16) + (message[j + 2] << 8) + message[j + 3]);
                    j += 4;
                    break;
                case "UInt16":
                    values[i] = (UInt16)((message[j] << 8) + message[j + 1]);
                    j += 2;
                    break;
                case "Byte":
                    values[i] = (byte)message[j++];
                    break;
                case "UInt32[]":
                    if (values[i] != null)
                    {
                        int len = ((UInt32[])values[i]).Length;
                        byte[] b = new byte[len * 4];
                        Array.Copy(message, j, b, 0, len * 4);
                        Array.Copy(Utilities.ByteArrayToUInt32Array(b), (UInt32[])values[i], len);
                        j += len * 4;
                    }
                    break;
                case "Byte[]":
                    if (values[i] != null)
                    {
                        int len = ((byte[])values[i]).Length;
                        Array.Copy(message, j, (byte[])(values[i]), 0, len);
                        j += len;
                    }
                    break;
                default:
                    throw new Exception("ByteExtractable::SetMessageBytes Unsupported Type: " + var[1] + " is of type " +  var[0]);
            }
        }
        FormatterServices.PopulateObjectMembers(this, members, values);
        return true;
    }
Cevap 05/08/2008 saat 14:47
kaynak kullanıcı

oy
2

her iki tarafta da .net ise:

Eğer ikili seri kullanmak ve byte [] Sonucu göndermesi gerektiğini düşünüyorum.

senin yapı güvenen sorun olabilir tam blittable olmak.

Bazı havai (cpu hem de ağda) ödeyecek ama güvenli olacaktır.

Cevap 05/08/2008 saat 14:29
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more