5

For a network protocol implementation I want to make use of the new Memory and Span classes to achieve zero-copy of the buffer while accessing the data through a struct.

I have the following contrived example:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Data
{
    public int IntValue;
    public short ShortValue;
    public byte ByteValue;
}

static void Prepare()
{
    var buffer = new byte[1024];
    var dSpan = MemoryMarshal.Cast<byte, Data>(buffer);
    ref var d = ref dSpan[0];

    d.ByteValue = 1;
    d.ShortValue = (2 << 8) + 3;
    d.IntValue = (4 << 24) + (5 << 16) + (6 << 8) + 7;
}

The result is that buffer is filled with 7, 6, 5, 4, 3, 2, 1, which is as desired, but I can hardly imagine that MemoryMarshal.Cast is the only way (bar anything requiring the unsafe keyword) to do this. I tried some other methods, but I can't figure out how to use them with either a ref struct (which can't be used as generic type argument) or how to get a struct that's in the actual buffer and not a copy (on which any mutations made are not reflected in the buffer).

Is there a some easier way to get this mutable struct from the buffer?

mycroes
  • 645
  • 8
  • 20
  • So what's a problem with memory.cast solution again? – Evk May 26 '18 at 20:41
  • You can always write c++ code to do the pointing like is done in many Net Library methods. – jdweng May 26 '18 at 22:01
  • @Evk no actual problem, just that it feels awkward having to change types to an array to get the first (and only) element. I can't really imagine this being the only way. – mycroes May 27 '18 at 22:21
  • @jdweng I'm not sure what you're referencing to ('like is done in many Net Library methods'), but I'm not sure if it would actually work. Also, I'd like this to use safe code only. – mycroes May 27 '18 at 22:26
  • c++ is used all the time with c# and will work. – jdweng May 28 '18 at 03:29
  • 1
    @jdweng Are you talking about manager C++ or native C++? Can you provide at least a single example of one of those 'many Net Library methods'? I've seen the source of many third party libraries, can't remember ever seeing C++ used in them. – mycroes May 28 '18 at 07:14
  • What is managed C++? There is MSDN c++ and native c++. Microsoft likes to invent there own world. – jdweng May 28 '18 at 09:54
  • 1
    @jdweng Managed C++: (https://en.wikipedia.org/wiki/Managed_Extensions_for_C%2B%2B) Could you please provide a usable answer (as an actual answer) or leave this question as is. – mycroes May 28 '18 at 18:34
  • 4
    @jdweng one of key points of `Span` is that it *is no longer necessary* to use either `unsafe` or C++ to exploit this kind of 100% managed / "safe" memory usage – Marc Gravell May 28 '18 at 22:18
  • The entire .NET Core standard API seems to be moving toward preferring `Span` over `byte[]` for these kinds of manipulations. The few Q&As about it are very hard to find because there aren't any specific tags. – StackOverthrow Sep 16 '19 at 17:50

1 Answers1

5

Oof. It looks like MemoryMarshal.Cast is what used to be the NonPortableCast extension method (from: this commit), in which case - yes, that's the appropriate way to thunk between layouts of spans, most commonly (but not exclusively) like in this case - between byte and some struct.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900