none
How to write a structure that contains a string value in Memory Mapped File? RRS feed

  • Question

  • Dear Sir,

    i have created following structure:-

     [StructLayout(LayoutKind.Explicit)]
            public struct Valuess  // as a Union
            {
                [FieldOffset(0)]
                public long lval;
                [FieldOffset(0)]
                public double rval;
                [FieldOffset(12)]
                [MarshalAs(UnmanagedType.AsAny)]
                public byte[] cval;
            };
            public struct SMDATA
            {
                public int type;
                public double AvgVal;
                public double MeanVal;
                public short projectLimoStatus;
                public short SystemLimoStatus;
                public short TestLimoStatus;
                public Valuess Val;  // object of above union
            }


    
    

    when i write data thru following code:-

    accessor.Write<T>(10,ref value);

    where accessor is the object of MemoryMappedViewAccessor class then an Argument exception occurs that "The Specified Type must be a structure containing no refrences. Parameter name:Type".

    if i remove the public byte[] cval from the Valuess structure then this code is working well but with this not working. but i need a string value into it because as per my requirment i will use one value at a time long,real or string.

    thanks in advance.

    
    
    Saturday, November 3, 2012 8:57 AM

All replies

  • Hello Sandeep Tiwari,

    1. The problem is that if "cval" is a byte[], its size must be specified in the "Valuess" structure, e.g. :

    [StructLayout(LayoutKind.Explicit)]
    public struct Valuess  // as a Union
    {
        [FieldOffset(0)]
        public long lval;
        [FieldOffset(0)]
        public double rval;
        [FieldOffset(12)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
        public byte[] cval;
    };
    1.1 In the above definition for "Valuess", "cval" is an embedded array of 11 bytes.

    2. As you intend "cval" to actually contain a string, you may also specify "cval" as an embedded string inside the "Valuess" structure, e.g. :

    [StructLayout(LayoutKind.Explicit)]
    public struct Valuess  // as a Union
    {
        [FieldOffset(0)]
        public long lval;
        [FieldOffset(0)]
        public double rval;
        [FieldOffset(12)]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
        public string cval;
    };

    2.1 In the above example, "cval" is an embedded string inside the "Valuess" structure of size 11 characters long (including the terminating NULL character).

    3. You may also specify that "cval" be a pointer to a C-style string, e.g. :

    [StructLayout(LayoutKind.Explicit)]
    public struct Valuess  // as a Union
    {
        [FieldOffset(0)]
        public long lval;
        [FieldOffset(0)]
        public double rval;
        [FieldOffset(12)]
        [MarshalAs(UnmanagedType.LPStr)]
        public string cval;
    };

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/


    • Edited by Lim Bio Liong Saturday, November 3, 2012 3:03 PM Added more explanation,
    • Proposed as answer by Pantelis44999 Saturday, November 3, 2012 10:28 PM
    Saturday, November 3, 2012 2:53 PM
  • Dear Sir,

    Thanks for your reply.

    Sir problem is that i already try all all types but problem still remains.

    my aim to read/write string type values in shared memory loaction by using above structure if u have another way then tell me ASAP but i am using same way in c++ then this is working properly.

    its' very urgent.

    Thanks in advance.

    Sunday, November 4, 2012 4:33 AM
  • Hello Sandeep,

    1. The C# structure itself cannot be mapped directly to the shared memory. It needs to be marshaled to it.

    2. The shared memory itself needs to be unmanaged.

    3. Hence a v important question : how do you transfer the C# structure from your C# code to the shared memory ?

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    Sunday, November 4, 2012 4:46 AM
  • Dear Sir,

    Thanks for your reply.

    i have written following code for write in shared memory.

    this is SharedMemory.cs file.

    using System;
    using System.IO;
    using System.Collections.Generic;
    using System.IO.MemoryMappedFiles;
    using System.Threading;
    
    namespace SMReader.SMFiles
    {
        public class SharedMemory<T> where T: struct
        {
            // Constructor
            public SharedMemory(string name, int size)
            {
                smName = name;
                smSize = size;
            }
    
            // Methods
            public bool Open()
            {
                try
                {
                    // Create named MMF
                    mmf = MemoryMappedFile.CreateOrOpen(smName, smSize);
                    
                    // Create accessors to MMF
                    accessor = mmf.CreateViewAccessor(0, smSize, MemoryMappedFileAccess.ReadWrite);
    
                    // Create lock
                    smLock = new Mutex(true, "SM_LOCK", out locked);
                }
                catch
                {
                    return false;
                }
    
                return true;
            }
    
            public void Close()
            {
                accessor.Dispose();
                mmf.Dispose();
                smLock.Close();
            }
    
            public T Data
            {
                get 
                {
                    T dataStruct;
                    accessor.Read<T>(10, out dataStruct);
                    return dataStruct; 
                }
                set 
                {
                    smLock.WaitOne();
                    accessor.Write<T>(10, ref value);
                    smLock.ReleaseMutex();
                }
            }
    
            // Data
            private string smName;
            private Mutex smLock;
            private int smSize;
            private bool locked;
            private MemoryMappedFile mmf;
            private MemoryMappedViewAccessor accessor;
        }
    }
    

    and this is Form1.cs file

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    using SMReader.SMFiles;
    
    namespace SMReader
    {
        public struct SMValues
        {
            public string csAtomNam;
            //public int bn;
            public SMValues(string c)
            {
                csAtomNam = string.Empty;
            }
            //public SMDATA Data;
        };
        public partial class Form1 : Form
        {
    
            SharedMemory<SMDATA> shmem;
            bool isReaderThreadRunning=false;
            public Form1()
            {
                InitializeComponent();
                try
                {
                    CreateSM();
                }
                catch (TypeLoadException ex)
                {
                    int i = 0;
                }
            }
            private void CreateSM()
            {
                shmem = new SharedMemory<SMDATA>("ShmemTest", 99);
                if (!shmem.Open())
                {
                    MessageBox.Show("Unable to open Shared Memory", "SharedMemory", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                WriteSM();
                //Thread MyThrd = new Thread(ReadSM);
            }
            private void WriteSM()
            {
                {
                    SMDATA Smval = new SMDATA();
                    Smval.type = (int)DataType.DT_ASC;
                    Smval.Val.cval = "sandeep";
                    shmem.Data = Smval;//for write data.
                    SMDATA sss = new SMDATA();
                    sss = shmem.Data;//for read data.
                }
            }
        }
    }
    

    and this is SMDefine.cs file

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace SMReader.SMFiles
    {      
            public enum DataType
            {
                DT_INT = 0x214,
                DT_REA = 0x215,
                DT_ASC = 0x216,
                DT_BOOL = 0x217,
                DT_INV = 0x218
            }
            [StructLayout(LayoutKind.Explicit)]
            public struct Valuess //Union
            {
                [FieldOffset(0)]
                public long lval;
                [FieldOffset(0)]
                public double rval;
                [FieldOffset(12)]
                [MarshalAs(UnmanagedType.ByValTStr,SizeConst=11)]
                public string cval;
            };
            public struct SMDATA //Structure
            {
                public int type;
                public double AvgVal;
                public double MeanVal;
                public short projectLimoStatus;
                public short SystemLimoStatus;
                public short TestLimoStatus;
                public Valuess Val; //Object of Union
            }
    }
    

    on above SharedMemory.cs file, system is throwing ArgumentException on above underline line.

    Sir Please help. its very urgent. the main problem is this that i cant change the above define structure because this structure is using in C++ code and i am moving my code C++ to c sharp so its tooo urgent.

    Sir please help. if there is any improvment then please update also.

    Sunday, November 4, 2012 1:21 PM
  • Hi Sandeep,

    Welcome to the MSDN forum.

    I'm moving the thread to the current forum for better support.

    Thanks for your understanding and have a nice day.


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us

    Monday, November 5, 2012 10:20 AM
    Moderator
  • Hello Sandeep Tiwari,

    1. I do not have .NET 4.0 on my PC and so I am not able to experiment with your code.

    2. However, I checked up the MemoryMappedViewAccessor Class on MSDN and also read up on an MSDN forum post that describes a problem that is v similar to yours :

    http://social.msdn.microsoft.com/Forums/fi-FI/csharpgeneral/thread/ed198d4d-2512-4c59-9ee1-643573eb012d

    3. It is surprising to me that according to the answerer to the above post, what we have attempted to do (i.e. using the MarshalAsAttribute to control marshaling) may not be possible. It is implied that marshaling is not performed by the MemoryMappedViewAccessor.Write<T>() method.

    4. However, from the above MSDN post, I think a possible solution to your current situation is to manually serialize the SMDATA structure into an array of bytes and then use the WriteArray<byte>() method to write the structure into the memory-mapped file.

    5. Here is an example code :

    static void DoTest()
    {
        // Instantiate a SMDATA structure.
        SMDATA smdata = new SMDATA();
        
        // Fill values.
        ...
        ...
        ...
        // Assign string value to "Val.cval" field.
        smdata.Val.cval = "HelloWorld";
    
        // Determine the size of the SMDATA as an unmanaged structure.
        int iSize = Marshal.SizeOf(typeof(SMDATA));
        // Allocate unmanaged memory of size iSize.
        IntPtr pSMDATA = Marshal.AllocHGlobal(iSize);
        // Allocate a managed byte array of size iSize.
        byte[] byteArray = new byte[iSize];
    
        // Marshal the managed structure smdata
        // into the unmanaged memory allocated earlier.
        Marshal.StructureToPtr(smdata, pSMDATA, false);
    
        // Next copy the bytes of the unmanaged SMDATA structure
        // into the byte array.
        Marshal.Copy(pSMDATA, byteArray, 0, iSize);
        
        // Perform the memory mapped file operation.
        accessor.WriteArray<byte>(iSomePosition, byteArray, 0, byteArray.Length);
    
        Marshal.FreeHGlobal(pSMDATA);
        pSMDATA = IntPtr.Zero;
    }

    6. Best of luck, Sandeep.

    - Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    Monday, November 5, 2012 3:46 PM
  • Dear Sir,

    Thanks for your reply.

    as per your suggestion, now i am able to write the structure into shared memory and read also but the problem is that if i want to write more than one structure in different location then it write properly but at the time of reading values are not coming correct i.e. i am able to write and read only one data in Shared memory. while i have created the Shared Memory size to sizeof(SMDATA)*No. of Elements to write in Memory.

    please help, it's very important.

    Thursday, November 8, 2012 4:14 AM
  • Hi Bio,

    Would you like to look at this thread again?

    Thank you.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Wednesday, November 14, 2012 1:26 PM
  • Hello Ghost,

    1. Thanks v much for your vote of confidence.

    2. However, I currently have no access to the MemoryMappedFile class on my development machine.

    3. Hence I am not able to help further.

    Sincere apologies,

    Bio.


    Please visit my blog : http://limbioliong.wordpress.com/

    Thursday, November 15, 2012 1:59 PM
  • Hi Lim,

    It is OK, Thank you very much for coming back to reply to me.

    Have a nice day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Tuesday, November 20, 2012 10:14 AM
  • Hi Lim,

    It is OK, Thank you very much for coming back to reply to me.

    Have a nice day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Dear Sir,

    Thanks for your reply.

    as per your suggestion, now i am able to write the structure into shared memory and read also but the problem is that if i want to write more than one structure in different location then it write properly but at the time of reading values are not coming correct i.e. i am able to write and read only one data in Shared memory. while i have created the Shared Memory size to sizeof(SMDATA)*No. of Elements to write in Memory.

    Tuesday, June 11, 2013 1:52 PM