-1

Consider the following code as an example of copying memory between a struct [] and a byte []. The method of memory copy is irrelevant to the core question. It's there to demonstrate two pointers to managed arrays.

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory (IntPtr dest, IntPtr src, uint count);

public struct MyStruct { public float Value; public TimeSpan Value; }

var bufferSize = 1000000;
var size = Marshal.SizeOf(typeof(MyStruct));
var bufferSource = new MyStruct [bufferSize];
var bufferTarget = new byte [bufferSize * size];

for (int i = 0; i < bufferSource.Length; i++)
{
    bufferSource [j] = new MyStruct() { Value = i; };
}

var handleSource = GCHandle.Alloc(bufferSource, GCHandleType.Pinned);
var handleTarget = GCHandle.Alloc(bufferTarget, GCHandleType.Pinned);
var pointerSource = handleSource.AddrOfPinnedObject();
var pointerTarget = handleTarget.AddrOfPinnedObject();
handleSource.Free();
handleTarget.Free();

CopyMemory(pointerTarget, pointerSource, (uint) (bufferSize * size));

The IntPtr pointerTarget did not originate as a MyStruct []. Is there a way to cast this allocated and initialized memory to a MyStruct []? I do not want to allocate a new array to be able to do this.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
Raheel Khan
  • 14,205
  • 13
  • 80
  • 168
  • 1
    Have you tried to adapt this - http://stackoverflow.com/questions/3278827/how-to-convert-a-structure-to-a-byte-array-in-c ? – Eugene Podskal Jul 30 '14 at 06:22
  • 1
    @EugenePodskal: The example seems to be about converting between bytes and structures. How does this apply to representing a `byte []` as a `struct []`? Maybe I'm missing something. – Raheel Khan Jul 30 '14 at 06:27
  • If you can get `struct` from `byte[]` and you know the size of the structure then what is the problem in getting multiple `struct` from `byte[]`? – Eugene Podskal Jul 30 '14 at 06:29
  • @EugenePodskal: That just gives me one `struct` at a time. My question is about how to access the memory as a `struct []` without having to reallocate memory (which is what would happen using the `PtrToStructure` for each struct). – Raheel Khan Jul 30 '14 at 06:39
  • Partially understood, but you'd better rework your question to more clearly express your goal, because as for me it is a bit hazy and misleading. And what is the reason for such manipulation in C# code? Pointers are usually used in PInvoke and .NET marshaling capabilities are quite capable to handle arrays of native structures. – Eugene Podskal Jul 30 '14 at 06:52

1 Answers1

1

It's easier to redefine the p/invoke signature, in this case like this:

[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
private static extern void CopyMemory([In, Out] byte[] pdst, Mystruct[] psrc, int cb);

define the struct layout for p/invoke:

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct { public float Value; public TimeSpan Value;}

Then you can just use it like this:

CopyMemory(bufferTarget, bufferSource, bufferTarget.Length);
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Since you're using `RtlMoveMemory`, I assume overlapped addresses are not an issue. This signature has the destination as a `byte []`. Is it possible to swap the source and destination types? And if so, it it because such a signature exists or that the runtime takes care of the marshaling internally? – Raheel Khan Jul 30 '14 at 07:02
  • 1
    Sure you can swap the parameters. There is no marshaling happening here. The CLR just uses the signature as you define it and sends things accordingly. It almost checks nothing. Since you enter unmanaged world, if the signature is wrong, you'll get exception, faults, you'll possibly mess memory, whatever. Here, because they're defined as arrays, it will pass these arrays as pointers; You can check the doc on this: http://msdn.microsoft.com/en-us/library/dd93y453(v=vs.110).aspx and http://msdn.microsoft.com/en-us/library/23acw07k(v=vs.110).aspx – Simon Mourier Jul 30 '14 at 10:01