सी # में एक बाइट सरणी में एक संरचना कैसे परिवर्तित करें?


83

मैं C # में एक संरचना को बाइट सरणी में कैसे बदलूं?

मैंने इस तरह एक संरचना को परिभाषित किया है:

public struct CIFSPacket
{
    public uint protocolIdentifier; //The value must be "0xFF+'SMB'".
    public byte command;

    public byte errorClass;
    public byte reserved;
    public ushort error;

    public byte flags;

    //Here there are 14 bytes of data which is used differently among different dialects.
    //I do want the flags2. However, so I'll try parsing them.
    public ushort flags2;

    public ushort treeId;
    public ushort processId;
    public ushort userId;
    public ushort multiplexId;

    //Trans request
    public byte wordCount;//Count of parameter words defining the data portion of the packet.
    //From here it might be undefined...

    public int parametersStartIndex;

    public ushort byteCount; //Buffer length
    public int bufferStartIndex;

    public string Buffer;
}

अपनी मुख्य विधि में, मैं इसका एक उदाहरण बनाता हूँ और इसे मान देता हूँ:

CIFSPacket packet = new CIFSPacket();
packet.protocolIdentifier = 0xff;
packet.command = (byte)CommandTypes.SMB_COM_NEGOTIATE;
packet.errorClass = 0xff;
packet.error = 0;
packet.flags = 0x00;
packet.flags2 = 0x0001;
packet.multiplexId = 22;
packet.wordCount = 0;
packet.byteCount = 119;

packet.Buffer = "NT LM 0.12";

अब मैं इस पैकेट को सॉकेट द्वारा भेजना चाहता हूं। उसके लिए, मुझे संरचना को बाइट सरणी में बदलने की आवश्यकता है। मैं यह कैसे कर सकता हूं?

मेरा पूरा कोड इस प्रकार है।

static void Main(string[] args)
{

  Socket MyPing = new Socket(AddressFamily.InterNetwork,
  SocketType.Stream , ProtocolType.Unspecified ) ;


  MyPing.Connect("172.24.18.240", 139);

    //Fake an IP Address so I can send with SendTo
    IPAddress IP = new IPAddress(new byte[] { 172,24,18,240 });
    IPEndPoint IPEP = new IPEndPoint(IP, 139);

    //Local IP for Receiving
    IPEndPoint Local = new IPEndPoint(IPAddress.Any, 0);
    EndPoint EP = (EndPoint)Local;

    CIFSPacket packet = new CIFSPacket();
    packet.protocolIdentifier = 0xff;
    packet.command = (byte)CommandTypes.SMB_COM_NEGOTIATE;
    packet.errorClass = 0xff;
    packet.error = 0;
    packet.flags = 0x00;
    packet.flags2 = 0x0001;
    packet.multiplexId = 22;
    packet.wordCount = 0;
    packet.byteCount = 119;

    packet.Buffer = "NT LM 0.12";

    MyPing.SendTo(It takes byte array as parameter);
}

एक कोड स्निपेट क्या होगा?


अंतिम पंक्ति MyPing.Send पर एक सुधार (यह पैरामीटर के रूप में बाइट सरणी लेता है); यह सेंड नहीं सेंडो है ......
स्वप्निल गुप्ता

हाय पेटर, मैं तुम्हें नहीं मिला ...
स्वप्निल गुप्ता

3
अपने पिछले प्रश्नों के कुछ उत्तर स्वीकार करना अच्छा हो सकता है।
19'10

1
मुझे संदेह है कि यह आपके द्वारा अपेक्षित आउटपुट के बारे में थोड़ा और विशिष्ट होने में मदद करेगा; वहाँ बहुत सारे तरीके हैं जो बाइट में बदल जाते हैं [] ... हम शायद इसके बारे में कुछ धारणाएँ बना सकते हैं, कि आप फ़ील्ड-ऑर्डर नेटवर्क-बाइट-ऑर्डर फ़िक्स्ड-साइज़ फ़ील्ड्स का प्रतिनिधित्व चाहते हैं - लेकिन क्या डोर?
मार्क ग्रेवेल

यदि आप मार्शल विकल्प का चयन करते हैं, तो ग्रैंड एंडियन और लिटिल एंडियन और लगभग 32 बिट्स / 64 बिट्स के बारे में ध्यान रखें।
x77

जवाबों:


126

मार्शलिंग का उपयोग करते हुए यह काफी आसान है।

फ़ाइल के ऊपर

using System.Runtime.InteropServices

समारोह

byte[] getBytes(CIFSPacket str) {
    int size = Marshal.SizeOf(str);
    byte[] arr = new byte[size];

    IntPtr ptr = Marshal.AllocHGlobal(size);
    Marshal.StructureToPtr(str, ptr, true);
    Marshal.Copy(ptr, arr, 0, size);
    Marshal.FreeHGlobal(ptr);
    return arr;
}

और इसे वापस परिवर्तित करने के लिए:

CIFSPacket fromBytes(byte[] arr) {
    CIFSPacket str = new CIFSPacket();

    int size = Marshal.SizeOf(str);
    IntPtr ptr = Marshal.AllocHGlobal(size);

    Marshal.Copy(arr, 0, ptr, size);

    str = (CIFSPacket)Marshal.PtrToStructure(ptr, str.GetType());
    Marshal.FreeHGlobal(ptr);

    return str;
}

आपकी संरचना में, आपको इसे एक स्ट्रिंग से पहले रखना होगा

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string Buffer;

और सुनिश्चित करें कि SizeConst आपके सबसे बड़े संभव स्ट्रिंग जितना बड़ा है।

और आपको शायद इसे पढ़ना चाहिए: http://msdn.microsoft.com/en-us/library/4ca6d5z7.aspx


धन्यवाद विनीत। गेटबाइट्स () को बाइट भेजने के बाद बुलाया जाना चाहिए [] ?? और frombytes () विधि बाइट्स भेज रही है? मैं थोड़ा उलझन में दोस्त हूँ?
स्वप्निल गुप्ता

1
GetBytes आपकी संरचना से एक सरणी में कनवर्ट करता है। FromBytes बाइट्स से वापस आपकी संरचना में कनवर्ट करता है। यह फ़ंक्शन हस्ताक्षरों से स्पष्ट है।
विंसेंट मैकनाब

1
@ स्वप्निल एक और सवाल है, जिसे आपको अलग से पूछना चाहिए। आपको सॉकेट्स पर CE ट्यूटोरियल के एक जोड़े को पूरा करने पर विचार करना चाहिए। बस Google सर्च करें।
विंसेंट मैकनाब

3
आपके fromBytes विधि में दो बार CIFSPacket को आवंटित करने की आवश्यकता नहीं है। Marshal.SizeOf खुशी से एक पैरामीटर के रूप में एक प्रकार लेगा और Mars.P.PTTTStructure एक नई प्रबंधित ऑब्जेक्ट आवंटित करता है।
जैक उलेजा

1
ध्यान दें कि कुछ परिस्थितियों में फ़ंक्शन «StructureToPtr» एक अपवाद फेंकता है। यह «सच» के बजाय «झूठी» पास करने के साथ तय किया जा सकता है Marshal.StructureToPtr(str, ptr, false);। लेकिन यह उल्लेख करने की आवश्यकता है कि मैं जेनेरिक से लिपटे हुए कार्यों का उपयोग कर रहा हूं, हालांकि ...
हाय-एंजेल

30

यदि आप वास्तव में चाहते हैं कि यह विंडोज पर फास्ट हो, तो आप इसे कॉपीमेरी के साथ असुरक्षित कोड का उपयोग करके कर सकते हैं। CopyMemory लगभग 5x तेज़ है (उदाहरण के लिए 800MB डेटा को marshalling के माध्यम से कॉपी करने के लिए 3s लगते हैं, जबकि केवल .Ms को CopyMemory के माध्यम से कॉपी करने में)। यह विधि आपको केवल उन डेटा का उपयोग करने के लिए सीमित करती है जो वास्तव में स्ट्रक्चर ब्लॉब में ही संग्रहीत हैं, जैसे संख्याएँ, या निश्चित लंबाई बाइट सरणियाँ।

    [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
    private static unsafe extern void CopyMemory(void *dest, void *src, int count);

    private static unsafe byte[] Serialize(TestStruct[] index)
    {
        var buffer = new byte[Marshal.SizeOf(typeof(TestStruct)) * index.Length];
        fixed (void* d = &buffer[0])
        {
            fixed (void* s = &index[0])
            {
                CopyMemory(d, s, buffer.Length);
            }
        }

        return buffer;
    }

4
जो लोग इस उत्तर को पढ़ रहे हैं, उनके सिर के रूप में .. यह क्रॉस प्लेटफ़ॉर्म अनुकूल नहीं है (यह विंडोज़ केवल कर्नेल 32.dll का उपयोग करता है)। लेकिन फिर, यह 2014 में लिखा गया था। :)
रेड

2
इसके अलावा संरचना को अनुक्रमिक होने की आवश्यकता होती है।
तोमर डब्ल्यू

25

इन तरीकों पर एक नजर:

byte [] StructureToByteArray(object obj)
{
    int len = Marshal.SizeOf(obj);

    byte [] arr = new byte[len];

    IntPtr ptr = Marshal.AllocHGlobal(len);

    Marshal.StructureToPtr(obj, ptr, true);

    Marshal.Copy(ptr, arr, 0, len);

    Marshal.FreeHGlobal(ptr);

    return arr;
}

void ByteArrayToStructure(byte [] bytearray, ref object obj)
{
    int len = Marshal.SizeOf(obj);

    IntPtr i = Marshal.AllocHGlobal(len);

    Marshal.Copy(bytearray,0, i,len);

    obj = Marshal.PtrToStructure(i, obj.GetType());

    Marshal.FreeHGlobal(i);
}

यह दूसरे धागे की बेशर्म कॉपी है जो मुझे गोगलिंग पर मिली थी!

अद्यतन : अधिक जानकारी के लिए, स्रोत की जाँच करें


मैं Marshalling का उपयोग कर बाइट सरणी के लिए संरचना संरचना है अब मैं कैसे जांच सकता हूं कि मुझे सॉकेट से प्रतिक्रिया मिल रही है या नहीं? कैसे करें जांच?
स्वप्निल गुप्ता

@Alairair, मुझे याद किया कि बाहर !! इसे इंगित करने के लिए धन्यवाद .. मैंने अपना उत्तर अपडेट कर दिया है।
अब्देल रावोफ

2
यह विकल्प प्लेटफ़ॉर्म डिपेंडेंट है - ग्रैंड एंडियन और लिटिल एंडियन और लगभग 32 बिट्स / 64 बिट्स के बारे में ध्यान रखें।
777 पर x77

@ एबडेल, और -1 चला गया है :)
एलेस्टेयर पिट्स

क्या यह एलोक प्रदर्शन करने के लिए समझ में आता है, एक कोशिश में मध्य बिट लपेटो, और फिर अंत में मुफ्त डाल दिया? ऐसा लगता नहीं है कि चीजें विफल होंगी, लेकिन अगर वे करते हैं, तो क्या मेमोरी कभी जारी होती है?
केसी

18

एक कम मेमोरी आवंटन के साथ विसेंट के कोड का वेरिएंट:

public static byte[] GetBytes<T>(T str)
{
    int size = Marshal.SizeOf(str);

    byte[] arr = new byte[size];

    GCHandle h = default(GCHandle);

    try
    {
        h = GCHandle.Alloc(arr, GCHandleType.Pinned);

        Marshal.StructureToPtr<T>(str, h.AddrOfPinnedObject(), false);
    }
    finally
    {
        if (h.IsAllocated)
        {
            h.Free();
        }
    }

    return arr;
}

public static T FromBytes<T>(byte[] arr) where T : struct
{
    T str = default(T);

    GCHandle h = default(GCHandle);

    try
    {
        h = GCHandle.Alloc(arr, GCHandleType.Pinned);

        str = Marshal.PtrToStructure<T>(h.AddrOfPinnedObject());

    }
    finally
    {
        if (h.IsAllocated)
        {
            h.Free();
        }
    }

    return str;
}

मैं GCHandleमेमोरी को "पिन" करने के लिए उपयोग करता हूं और फिर मैं सीधे इसके पते का उपयोग करता हूं h.AddrOfPinnedObject()


हटा देना चाहिए where T : structअन्यथा Tपास होने की शिकायत होगी non-nullable type
codenamezero

GCHandle.Allocविफल हो जाएगा यदि संरचना में गैर-ब्लिट करने योग्य डेटा है, उदाहरण के लिए
जो

@ जो आप सही हैं। कोड दिए गए ढांचे के लिए लिखा गया था, जिसमें केवल दमदार प्रकार थे और string
xanatos

5

जैसा कि मुख्य उत्तर CIFSPacket प्रकार का उपयोग कर रहा है, जो C # में उपलब्ध नहीं है (या अब नहीं है), मैंने सही तरीके लिखे:

    static byte[] getBytes(object str)
    {
        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);

        return arr;
    }

    static T fromBytes<T>(byte[] arr)
    {
        T str = default(T);

        int size = Marshal.SizeOf(str);
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.Copy(arr, 0, ptr, size);

        str = (T)Marshal.PtrToStructure(ptr, str.GetType());
        Marshal.FreeHGlobal(ptr);

        return str;
    }

परीक्षित, वे काम करते हैं।


4

मुझे पता है कि यह वास्तव में देर हो चुकी है, लेकिन C # 7.3 के साथ आप अनवांटेड स्ट्रक्चर्स या ऐसी किसी भी चीज़ के लिए यह कर सकते हैं जो अनमैंग्ड (इंट, बूल आदि ...):

public static unsafe byte[] ConvertToBytes<T>(T value) where T : unmanaged {
        byte* pointer = (byte*)&value;

        byte[] bytes = new byte[sizeof(T)];
        for (int i = 0; i < sizeof(T); i++) {
            bytes[i] = pointer[i];
        }

        return bytes;
    }

तो इस तरह का उपयोग करें:

struct MyStruct {
        public int Value1;
        public int Value2;
        //.. blah blah blah
    }

    byte[] bytes = ConvertToBytes(new MyStruct());

2

आप मार्शल (StructureToPtr, ptrToStructure), और Mars.c.copy का उपयोग कर सकते हैं लेकिन यह प्लेटफॉर्म पर निर्भर है।


Serialization में Custom Serialization के कार्य शामिल हैं।

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext) 

SerializationInfo में प्रत्येक सदस्य को क्रमबद्ध करने के लिए कार्य शामिल हैं।


बाइनरीविटर और बाइनरीरीडर में बाइट ऐरे (स्ट्रीम) को सेव / लोड करने के तरीके भी शामिल हैं।

ध्यान दें कि आप एक बाइट ऐरे से एक मेमोरीस्ट्रीम बना सकते हैं या एक मेमोरीस्ट्रीम से बाइट एरे को।

आप अपनी संरचना पर एक विधि सहेजें और एक विधि नया बना सकते हैं:

   Save(Bw as BinaryWriter)
   New (Br as BinaryReader)

फिर आप सेव / लोड टू स्ट्रीम -> बाइट ऐरे में सदस्यों का चयन करें।


1

यह बहुत सीधा किया जा सकता है।

स्पष्ट रूप से अपनी संरचना को परिभाषित करें [StructLayout(LayoutKind.Explicit)]

int size = list.GetLength(0);
IntPtr addr = Marshal.AllocHGlobal(size * sizeof(DataStruct));
DataStruct *ptrBuffer = (DataStruct*)addr;
foreach (DataStruct ds in list)
{
    *ptrBuffer = ds;
    ptrBuffer += 1;
}

यह कोड केवल असुरक्षित संदर्भ में लिखा जा सकता है। addrजब आपको इसके साथ काम करना हो तो आपको मुक्त करना होगा।

Marshal.FreeHGlobal(addr);

एक निश्चित आकार के संग्रह पर स्पष्ट आदेश दिए गए संचालन करते समय, आपको संभवतः एक सरणी और फ़ोर-लूप का उपयोग करना चाहिए। सरणी क्योंकि यह निश्चित आकार है, और फॉर-लूप क्योंकि फ़ॉरच्यू को आपके द्वारा अपेक्षित प्रकार के आदेश में होने की गारंटी नहीं है, जब तक कि आप अपनी प्रकार की सूची के अंतर्निहित कार्यान्वयन को नहीं जानते हैं और यह गणना योग्य है, और यह कभी नहीं बदलेगा। उदाहरण के लिए, अंत से शुरू करने और पीछे जाने के लिए प्रगणक को परिभाषित कर सकता है।

1

मैं एक अलग दृष्टिकोण के साथ आया हूं जो लंबाई को ठीक करने की परेशानी के बिना किसी भी रूपांतरित कर सकता है struct, हालांकि परिणामस्वरूप बाइट सरणी में थोड़ा अधिक हेडहेड होगा।

यहाँ एक नमूना है struct:

[StructLayout(LayoutKind.Sequential)]
public class HelloWorld
{
    public MyEnum enumvalue;
    public string reqtimestamp;
    public string resptimestamp;
    public string message;
    public byte[] rawresp;
}

जैसा कि आप देख सकते हैं, उन सभी संरचनाओं को निश्चित लंबाई विशेषताओं को जोड़ने की आवश्यकता होगी। जो अक्सर आवश्यकता से अधिक स्थान लेने पर समाप्त हो सकता था। ध्यान दें कि LayoutKind.Sequentialआवश्यक है, क्योंकि हम चाहते हैं कि प्रतिबिंब हमेशा हमें एक ही क्रम प्रदान करता है जब के लिए खींच रहा हो FieldInfo। मेरी प्रेरणा TLVटाइप-लेंथ-वैल्यू से है। कोड पर एक नजर डालते हैं:

public static byte[] StructToByteArray<T>(T obj)
{
    using (MemoryStream ms = new MemoryStream())
    {
        FieldInfo[] infos = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance);
        foreach (FieldInfo info in infos)
        {
            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream inms = new MemoryStream()) {

                bf.Serialize(inms, info.GetValue(obj));
                byte[] ba = inms.ToArray();
                // for length
                ms.Write(BitConverter.GetBytes(ba.Length), 0, sizeof(int));

                // for value
                ms.Write(ba, 0, ba.Length);
            }
        }

        return ms.ToArray();
    }
}

उपरोक्त फ़ंक्शन का उपयोग केवल BinaryFormatterअज्ञात आकार को कच्चा करने के लिए किया जाता है object, और मैं बस आकार का ट्रैक रखता हूं और इसे आउटपुट के अंदर MemoryStreamभी संग्रहीत करता हूं ।

public static void ByteArrayToStruct<T>(byte[] data, out T output)
{
    output = (T) Activator.CreateInstance(typeof(T), null);
    using (MemoryStream ms = new MemoryStream(data))
    {
        byte[] ba = null;
        FieldInfo[] infos = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance);
        foreach (FieldInfo info in infos)
        {
            // for length
            ba = new byte[sizeof(int)];
            ms.Read(ba, 0, sizeof(int));

            // for value
            int sz = BitConverter.ToInt32(ba, 0);
            ba = new byte[sz];
            ms.Read(ba, 0, sz);

            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream inms = new MemoryStream(ba))
            {
                info.SetValue(output, bf.Deserialize(inms));
            }
        }
    }
}

जब हम इसे अपने मूल में बदलना चाहते हैं structतो हम केवल लंबाई को वापस पढ़ते हैं और सीधे इसे वापस डंप करते हैं BinaryFormatterजिसमें बदले में इसे वापस डंप करते हैं struct

ये 2 कार्य सामान्य हैं और किसी के साथ भी काम करना चाहिए struct , मैंने अपनी C#परियोजना में उपरोक्त कोड का परीक्षण किया है, जहां मेरे पास एक सर्वर और एक क्लाइंट है, जुड़ा हुआ है और इसके माध्यम से संवाद करता है NamedPipeStreamऔर मैं अपने structबाइट सरणी को एक से दूसरे और आगे के रूप में अग्रेषित करता हूं और इसे वापस परिवर्तित करता हूं ।

मेरा मानना ​​है कि मेरा दृष्टिकोण बेहतर हो सकता है, क्योंकि यह structअपने आप ही लंबाई को ठीक नहीं करता है और एकमात्र ओवरहेड intआपकी संरचना में आपके लिए हर क्षेत्र के लिए बस है । बाइट सरणी के अंदर कुछ छोटे बिट ओवरहेड भी हैं BinaryFormatter, लेकिन इसके अलावा, बहुत ज्यादा नहीं है।


6
आमतौर पर, जब लोग इस तरह के सामान से निपटने की कोशिश कर रहे होते हैं, तो वे क्रमबद्ध प्रदर्शन के बारे में भी चिंतित होते हैं। सिद्धांत रूप में, किसी भी प्रकार की संरचना को महंगे क्रमांकन और कॉपी किए बिना बाइट सरणी के रूप में पुनर्व्याख्या की जा सकती है।
तनवीर बदर

0

मैं बाइनरीरीडर और बाइनरीविटर कक्षाओं पर एक नज़र डालूंगा। मुझे हाल ही में एक बाइट सरणी (और पीछे) के लिए डेटा को क्रमबद्ध करना पड़ा और मूल रूप से खुद को फिर से लिखने के बाद मैंने इन कक्षाओं को पाया।

http://msdn.microsoft.com/en-us/library/system.io.binarywriter.aspx

उस पेज पर एक अच्छा उदाहरण भी है।


0

कुछ बाहरी पुस्तकालय के लिए एक पूर्वनिर्धारित (सी स्तर) संरचना की तरह दिखता है। मार्शल आपका दोस्त है। जाँच:

http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx

कैसे इस से निपटने के लिए एक स्टार्टर के लिए। ध्यान दें कि आप कर सकते हैं - विशेषताओं के साथ - बाइट लेआउट और स्ट्रिंग हैंडलिंग जैसी चीजों को परिभाषित करें। वास्तव में बहुत अच्छा तरीका है।

उसके लिए न तो बाइनरीफ़ॉर्मेटर न ही मेमोरीस्ट्रीम किया जाता है।


0

@Abdel Olakara जवाब दान में .net 3.5 में काम नहीं करता है, नीचे के रूप में संशोधित किया जाना चाहिए:

    public static void ByteArrayToStructure<T>(byte[] bytearray, ref T obj)
    {
        int len = Marshal.SizeOf(obj);
        IntPtr i = Marshal.AllocHGlobal(len);
        Marshal.Copy(bytearray, 0, i, len);
        obj = (T)Marshal.PtrToStructure(i, typeof(T));
        Marshal.FreeHGlobal(i);
    }

0
        Header header = new Header();
        Byte[] headerBytes = new Byte[Marshal.SizeOf(header)];
        Marshal.Copy((IntPtr)(&header), headerBytes, 0, headerBytes.Length);

यह चाल जल्दी करना चाहिए, है ना?


GCHandle संस्करण कहीं बेहतर है।
Пет17р Петров

0

यहां यह उदाहरण केवल शुद्ध ब्लिटेबल प्रकारों पर लागू होता है, उदाहरण के लिए, ऐसे प्रकार जो सीधे सी में यादगार हो सकते हैं।

उदाहरण - अच्छी तरह से ज्ञात 64-बिट संरचना

[StructLayout(LayoutKind.Sequential)]  
public struct Voxel
{
    public ushort m_id;
    public byte m_red, m_green, m_blue, m_alpha, m_matid, m_custom;
}

इस तरह से परिभाषित, संरचना स्वचालित रूप से 64-बिट के रूप में पैक की जाएगी।

अब हम स्वरों की मात्रा बना सकते हैं:

Voxel[,,] voxels = new Voxel[16,16,16];

और उन सभी को एक बाइट सरणी में सहेजें:

int size = voxels.Length * 8; // Well known size: 64 bits
byte[] saved = new byte[size];
GCHandle h = GCHandle.Alloc(voxels, GCHandleType.Pinned);
Marshal.Copy(h.AddrOfPinnedObject(), saved, 0, size);
h.Free();
// now feel free to save 'saved' to a File / memory stream.

हालाँकि, चूंकि ओपी यह जानना चाहता है कि संरचना को कैसे परिवर्तित किया जाए, हमारी Voxel संरचना में निम्नलिखित विधि हो सकती है ToBytes:

byte[] bytes = new byte[8]; // Well known size: 64 bits
GCHandle h = GCHandle.Alloc(this, GCHandleType.Pinned);
Marshal.Copy(hh.AddrOfPinnedObject(), bytes, 0, 8);
h.Free();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.