3
[StructLayout(LayoutKind.Explicit)]
public struct struct1
{
    [FieldOffset(0)]
        public byte a;   // 1 byte
    [FieldOffset(1)]
        public int b;    // 4 bytes
    [FieldOffset(5)]
        public short c;  // 2 bytes
    [FieldOffset(7)]
        public byte buffer;
    [FieldOffset(18)]
        public byte[] shaHashResult;   // 20 bytes
}

void DoStuff()
{
   struct1 myTest = new struct1();
   myTest.shaHashResult =  sha256.ComputeHash(pkBytes);  // 20 bytes

   byte[] newParameter = myTest.ToArray() //<-- How do I convert a struct 
                                          //     to array without a copy?
}

How do I take the array myTest and convert it to a byte[]? Since my objects will be large, I don't want to copy the array (memcopy, etc)

makerofthings7
  • 60,103
  • 53
  • 215
  • 448
  • @SLaks I found this but no corollary: `System.Runtime.InteropServices.Marshal.StructureToPtr` – makerofthings7 Dec 17 '12 at 22:36
  • 3
    If you want to avoid copying, you may want to change that to a `class`. – SLaks Dec 17 '12 at 22:36
  • 2
    The byte array that you assign is just a pointer. It is not inlined. – codekaizen Dec 17 '12 at 22:43
  • @codekaizen has a very important point. The bytes in the shaHashResult array are not in the struct. They are somewhere out in the heap. The struct only has a reference to the array object. – hatchet - done with SOverflow Dec 17 '12 at 22:48
  • Sigh... and I thought I was on a good track when I came up with using a stuct and /or Marshal – makerofthings7 Dec 17 '12 at 22:52
  • The reason this will never work is in the implementation of `ComputeHash` is a statement which is essentially `new Byte[20]`. This will always allocate a new array on the GC heap, implying a copy will need to be performed. – codekaizen Dec 17 '12 at 23:13
  • Here is a similar SO question discussing the issue of trying to inline an array in the struct. http://stackoverflow.com/questions/690382/how-can-i-put-an-array-inside-a-struct-in-c – hatchet - done with SOverflow Dec 17 '12 at 23:16

1 Answers1

0

Since you have a big array, this is really the only way you will be able to do what you want:

var myBigArray = new Byte[100000];

// ...

var offset = 0;
var hash = sha256.ComputeHash(pkBytes);
Buffer.BlockCopy(myBigArray, offset, hash, 0, hash.Length);

// if you are in a loop, do something like this
offset += hash.Length;

This code is very efficient, and even in a tight loop, the results of ComputeHash will be collected in a quick Gen0 collection, while myBigArray will be on the Large Object Heap, and not moved or collected. The Buffer.BlockCopy is highly optimized in the runtime, yielding the fastest copy you could probably achieve, even in the face of pinning the target, and using an unrolled pointer copy.

codekaizen
  • 26,990
  • 7
  • 84
  • 140