与C ++到C#的内存映射文件共享链式结构

时间:2017-11-01 15:54:41

标签: c# c++

根据我的另一个问题here,由于这个社区,我已经能够将C ++中的字符串共享到C#。

但是,我需要达到一个级别,我需要使用内存映射从C ++到C#共享链式结构。

在示例场景中:

我的C ++结构:

struct STRUCT_2
{
    char Name[260];
};

struct STRUCT_1
{
    void Init()
    {
        this->Count = 0;
        this->Index = 0;
    }

    DWORD Count;
    DWORD Index;
    STRUCT_2 Table[256];
};

我试图将其“转移”到C#:

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
public unsafe struct STRUCT_2
{
   [FieldOffset(0)]
   public fixed char Name[260];
}

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
public unsafe struct STRUCT_1
{
   void Init()
   {
     this.Count = 0;
     this.Index = 0;
   }
   [FieldOffset(0)]
   public uint Count;
   [FieldOffset(0)]
   public uint Index;
   [FieldOffset(100)]
   [MarshalAs(UnmanagedType.LPStruct, SizeConst = 256)]
   public STRUCT_2 Table;
}

这部分有效,基本上我可以看到来自计数索引的值,但是我无法看到值,甚至无法在 STRUCT_2 中获取它们

我试图改变:

public STRUCT_2[] Table;

然后编译器告诉我:

“指定的Type必须是不包含引用的结构。”

所以我的问题是,如何在C#中使用 MemoryMappedFile 读取结构中的结构?

非常欢迎建议,想法或例子。

更新

在C#中填写可测试代码:

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public unsafe struct STRUCT_2
        {
            [FieldOffset(0)]
            public fixed byte Name[260];
            // Fix thanks to Ben Voigt
        }

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public unsafe struct STRUCT_1
        {
            void Init()
            {
                this.Count = 0;
                this.Index = 0;
            }
            [FieldOffset(0)]
            public uint Count;
            [FieldOffset(0)]
            public uint Index;
            [FieldOffset(100)]
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public STRUCT_2[] Table;
        }

        static void Main(string[] args)
        {
            MemoryMappedFileSecurity CustomSecurity = new MemoryMappedFileSecurity();
            CustomSecurity.AddAccessRule(new System.Security.AccessControl.AccessRule<MemoryMappedFileRights>("everyone", MemoryMappedFileRights.FullControl, System.Security.AccessControl.AccessControlType.Allow));

            var mappedFile = MemoryMappedFile.CreateOrOpen("Local\\STRUCT_MAPPING", 1024, MemoryMappedFileAccess.ReadWriteExecute, MemoryMappedFileOptions.None, CustomSecurity, System.IO.HandleInheritability.Inheritable);

            using (var accessor = mappedFile.CreateViewAccessor())
            {
                STRUCT_1 data;

                accessor.Read<STRUCT_1>(0, out data); // ERROR !
                //The specified Type must be a struct containing no references.

                Console.WriteLine(data.Count);
                Console.WriteLine(data.Index);
            }
        }

1 个答案:

答案 0 :(得分:1)

检查一下。

在Visual Studio 2017上测试,Windows 7 x64。

写入和读取数据可以找到。

这对我来说也很好。

花点时间。

一帆风顺!

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct STRUCT_2
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
        public  byte[]  Name;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
    public struct STRUCT_1
    {
        void Init()
        {
            this.Count = 0;
            this.Index = 0;
        }
        public uint Count;
        public uint Index;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] //! array size of 10.
        public STRUCT_2 [] Table;
    }

    static void test3()
    {

        MemoryMappedFileSecurity CustomSecurity = new MemoryMappedFileSecurity();
        CustomSecurity.AddAccessRule(new System.Security.AccessControl.AccessRule<MemoryMappedFileRights>
            ( "everyone"
            , MemoryMappedFileRights.FullControl
            , System.Security.AccessControl.AccessControlType.Allow));

        using (var mappedFile = MemoryMappedFile.CreateOrOpen("Local\\STRUCT_MAPPING"
                                                    , 10 * 1024
                                                    , MemoryMappedFileAccess.ReadWriteExecute
                                                    , MemoryMappedFileOptions.None
                                                    , CustomSecurity
                                                    , System.IO.HandleInheritability.Inheritable))
        { 
            using (var accessor = mappedFile.CreateViewAccessor())
            {
                //! test setting.
                int table_count = 5;

                //! write data.
                STRUCT_1 write_data;
                write_data.Index = 1;
                write_data.Count = 2;
                write_data.Table = new STRUCT_2[10];

                for (int i = 0; i < 10; i++)
                {
                    write_data.Table[i].Name = new byte[260];
                    write_data.Table[i].Name[0] = (byte)i;
                }

                //! ----------------------------
                // Get size of struct
                int size = Marshal.SizeOf(typeof(STRUCT_1));
                byte[] data = new byte[size];

                // Initialize unmanaged memory.
                IntPtr p = Marshal.AllocHGlobal(size);

                // Copy struct to unmanaged memory.
                Marshal.StructureToPtr(write_data, p, false);

                // Copy from unmanaged memory to byte array.
                Marshal.Copy(p, data, 0, size);

                // Write to memory mapped file.
                accessor.WriteArray<byte>(0, data, 0, data.Length);

                // Free unmanaged memory.
                Marshal.FreeHGlobal(p);
                p = IntPtr.Zero;

                //! ----------------------------------------------
                STRUCT_1 read_data;
                size = Marshal.SizeOf(typeof(STRUCT_1));
                data = new byte[size];

                // Initialize unmanaged memory.
                p = Marshal.AllocHGlobal(size);


                // Read from memory mapped file.
                accessor.ReadArray<byte>(0, data, 0, data.Length);

                // Copy from byte array to unmanaged memory.
                Marshal.Copy(data, 0, p, size);

                // Copy unmanaged memory to struct.
                read_data = (STRUCT_1)Marshal.PtrToStructure(p, typeof(STRUCT_1));

                // Free unmanaged memory.
                Marshal.FreeHGlobal(p);
                p = IntPtr.Zero;


                Console.WriteLine(read_data.Index);
                Console.WriteLine(read_data.Count);
            }
        }
    }