Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. How to copy struct to byte [] ?

How to copy struct to byte [] ?

Scheduled Pinned Locked Moved C#
csharpquestiondata-structuresjsontutorial
3 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Q Offline
    Q Offline
    queisser
    wrote on last edited by
    #1

    I need to call an unmanaged function that takes, basically, a void pointer to a buffer. I've got the transfer to the unmanaged DLL working by passing a byte [] and letting .NET marshal. However, the buffer may contain different data structures on different calls since it's a kind of generic entry point with the exact function specified in the first field. In C I would do something like this: char buf[1000]; struct Header { int cmd; int flags; int param; }; struct Cmd1SpecificData { double param1ForCommand1; short param2ForCommand1; short param3ForCommand1; // and so on... }; void foo() { Header *header = (Header *)buf; Cmd1SpecificData = (Cmd1SpecificData *)(header + 1); header->cmd = 1; header->flags = 999; Cmd1SpecificData->param1ForCommand1 = 123.456; APICALL(buf); } APICALL can now look at the first field and figure out what to do. In C# I don't quite know how to do this. I have a byte [] which is the equivalent of the char buf[] but how do I cast pointers into the byte []? I couldn't find a simple way to copy data from a struct to a byte [] or how to use a MemoryStream to stream the data into the byte []. My questions: 1) What's the best way of getting the contents of a struct into a byte array? Note that I'll need to get different structures chained together so I might need to put the contents of the structs at specific offsets in the byte array. 2) Is there a fundamentally better way of getting .NET data to an API of this sort? Maybe I should do the marshalling myself and convert everything to a pointer before calling the unmanaged code? Thanks, Andrew Queisser

    B L 2 Replies Last reply
    0
    • Q queisser

      I need to call an unmanaged function that takes, basically, a void pointer to a buffer. I've got the transfer to the unmanaged DLL working by passing a byte [] and letting .NET marshal. However, the buffer may contain different data structures on different calls since it's a kind of generic entry point with the exact function specified in the first field. In C I would do something like this: char buf[1000]; struct Header { int cmd; int flags; int param; }; struct Cmd1SpecificData { double param1ForCommand1; short param2ForCommand1; short param3ForCommand1; // and so on... }; void foo() { Header *header = (Header *)buf; Cmd1SpecificData = (Cmd1SpecificData *)(header + 1); header->cmd = 1; header->flags = 999; Cmd1SpecificData->param1ForCommand1 = 123.456; APICALL(buf); } APICALL can now look at the first field and figure out what to do. In C# I don't quite know how to do this. I have a byte [] which is the equivalent of the char buf[] but how do I cast pointers into the byte []? I couldn't find a simple way to copy data from a struct to a byte [] or how to use a MemoryStream to stream the data into the byte []. My questions: 1) What's the best way of getting the contents of a struct into a byte array? Note that I'll need to get different structures chained together so I might need to put the contents of the structs at specific offsets in the byte array. 2) Is there a fundamentally better way of getting .NET data to an API of this sort? Maybe I should do the marshalling myself and convert everything to a pointer before calling the unmanaged code? Thanks, Andrew Queisser

      B Offline
      B Offline
      Bojan Rajkovic
      wrote on last edited by
      #2

      Well, to copy a struct to a byte[], you need some marshaling code..It uses the Marshal class (as if that wasn't obvious) to allocate some memory..Like this: (i usually declare methods like this as an instance method and a static method with a parameter of whatever type it's defined in)public byte[] ToBytes() { byte[] buff = new byte[Marshal.SizeOf(typeof(MyType))]; GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned); Marshal.StructureToPtr(this, handle.AddrOfPinnedObject(), false); handle.Free(); return buff; }
      That code will marshal the struct to a byte[], and from that code, the code for marshaling back to a struct comes easy:public static MyType FromBytes(byte[] buff) { GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned); MyType mt = (MyType)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MyType)); // because ptrtostructure returns an object :-\ handle.Free(); return mt; }
      Now as for chaining structures together, you can do that yourself using Array.Copy() and copying into a byte[] Passing back the data as an IntPtr requires only slight modification to the original functions:

      public IntPtr ToIntPtr()
      {
         byte[] buff = new byte[Marshal.SizeOf(typeof(MyType))];
         IntPtr handle = Marshal.AllocHGlobal(buff.Length);
         Marshal.StructureToPtr(this, handle, true); // passing false for that last param can cause memory leaks
         return handle;
      }
      
      public static MyType FromIntPtr(IntPtr ptr)
      {
         MyType mt = (MyType)Marshal.PtrToStructure(ptr, typeof(MyType)); // because ptrtostructure returns an object :-\
         //Marshal.FreeHGlobal(ptr); - only do this if you know you won't be using that IntPtr again
         return mt;
      }
      

      Note: That code is not 100% guaranteed to compile or work, I didn't test it very much, but it should work, and the basic concept is more or less correct. If you have any more questions, feel free to ask.

      1 Reply Last reply
      0
      • Q queisser

        I need to call an unmanaged function that takes, basically, a void pointer to a buffer. I've got the transfer to the unmanaged DLL working by passing a byte [] and letting .NET marshal. However, the buffer may contain different data structures on different calls since it's a kind of generic entry point with the exact function specified in the first field. In C I would do something like this: char buf[1000]; struct Header { int cmd; int flags; int param; }; struct Cmd1SpecificData { double param1ForCommand1; short param2ForCommand1; short param3ForCommand1; // and so on... }; void foo() { Header *header = (Header *)buf; Cmd1SpecificData = (Cmd1SpecificData *)(header + 1); header->cmd = 1; header->flags = 999; Cmd1SpecificData->param1ForCommand1 = 123.456; APICALL(buf); } APICALL can now look at the first field and figure out what to do. In C# I don't quite know how to do this. I have a byte [] which is the equivalent of the char buf[] but how do I cast pointers into the byte []? I couldn't find a simple way to copy data from a struct to a byte [] or how to use a MemoryStream to stream the data into the byte []. My questions: 1) What's the best way of getting the contents of a struct into a byte array? Note that I'll need to get different structures chained together so I might need to put the contents of the structs at specific offsets in the byte array. 2) Is there a fundamentally better way of getting .NET data to an API of this sort? Maybe I should do the marshalling myself and convert everything to a pointer before calling the unmanaged code? Thanks, Andrew Queisser

        L Offline
        L Offline
        leppie
        wrote on last edited by
        #3

        Best way it to create a pinned pointer, then it looks/works like C. EG

        byte[] buf = new byte[1000];
        unsafe
        {
        fixed (byte* b = buf)
        {
        Header *header = (Header *)b;
        Cmd1SpecificData* specdata = (Cmd1SpecificData *)(header + 1);
        header->cmd = 1;
        header->flags = 999;
        specdata->param1ForCommand1 = 123.456;

        APICALL(b);
        

        }
        }

        xacc-ide 0.0.15 now with C#, MSIL, C, XML, ASP.NET, Nemerle, MyXaml and HLSL coloring - Screenshots

        1 Reply Last reply
        0
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • World
        • Users
        • Groups