Search code examples
c#memory-mapped-filesintptr

How to get an IntPtr to access the view of a MemoryMappedFile?


Is there a way to get a direct IntPtr to the data in a MemoryMappedFile? I have large data block with high frequency change and I don't want to copy it


Solution

  • No, not an IntPtr, that doesn't help you anyway. You can get a byte*, you can cast it at will to access the actual data type. And you can cast it to IntPtr if you have to. Having to use the unsafe keyword is quite intentional.

    Create a MemoryMappedViewAccessor to create the view on the MMF. Then use the AcquirePointer() method of its SafeMemoryMappedViewHandle property to obtain the byte*.

    A sample program that demonstrates the usage and shows various pointer shenanigans:

    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    class Program {
        static unsafe void Main(string[] args) {
            using (var mmf = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateNew("test", 42))
            using (var view = mmf.CreateViewAccessor()) {
                byte* poke = null;
                view.SafeMemoryMappedViewHandle.AcquirePointer(ref poke);
                *(int*)poke = 0x12345678;
                Debug.Assert(*poke == 0x78);
                Debug.Assert(*(poke + 1) == 0x56);
                Debug.Assert(*(short*)poke == 0x5678);
                Debug.Assert(*((short*)poke + 1) == 0x1234);
                Debug.Assert(*(short*)(poke + 2) == 0x1234);
                IntPtr ipoke = (IntPtr)poke;
                Debug.Assert(Marshal.ReadInt32(ipoke) == 0x12345678);
                *(poke + 1) = 0xab;
                Debug.Assert(Marshal.ReadInt32(ipoke) == 0x1234ab78);
                view.SafeMemoryMappedViewHandle.ReleasePointer();
            }
        }
    }