天天看點

共享記憶體操作類(C#源碼)

VC++的共享記憶體操作代碼實作起來相對比較容易,但是用C#語言來實作,就有一定難度,由于工作需要,把以前VC開發的共享記憶體代碼要用C#實作,别說,還費了不少周折,畢竟C#操作API函數和位址指針不是那麼直接

,還好,總算完成了,效果還不錯。

共享記憶體操作類(C#源碼)
共享記憶體操作類:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ShareMemLib
{
    public class ShareMem
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);
        
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr OpenFileMapping(int dwDesiredAccess,[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,string lpName);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr MapViewOfFile(IntPtr hFileMapping,uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow,uint dwNumberOfBytesToMap);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        [DllImport("kernel32", EntryPoint="GetLastError")]
        public static extern int GetLastError ();

        const int ERROR_ALREADY_EXISTS = 183;

        const int FILE_MAP_COPY = 0x0001;
        const int FILE_MAP_WRITE = 0x0002;
        const int FILE_MAP_READ = 0x0004;
        const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;

        const int PAGE_READONLY = 0x02;
        const int PAGE_READWRITE = 0x04;
        const int PAGE_WRITECOPY = 0x08;
        const int PAGE_EXECUTE = 0x10;
        const int PAGE_EXECUTE_READ = 0x20;
        const int PAGE_EXECUTE_READWRITE = 0x40;

        const int SEC_COMMIT = 0x8000000;
        const int SEC_IMAGE = 0x1000000;
        const int SEC_NOCACHE = 0x10000000;
        const int SEC_RESERVE = 0x4000000;

        const int INVALID_HANDLE_VALUE = -1;

        IntPtr m_hSharedMemoryFile = IntPtr.Zero;
        IntPtr m_pwData = IntPtr.Zero;
        bool m_bAlreadyExist = false;
        bool m_bInit = false;
        long m_MemSize=0;

        public ShareMem()
        {
        }
        ~ShareMem()
        {
            Close();
        }

        /// <summary>
        /// 初始化共享記憶體
        /// </summary>
        /// <param name="strName">共享記憶體名稱</param>
        /// <param name="lngSize">共享記憶體大小</param>
        /// <returns></returns>
        public int Init(string strName, long lngSize)
        {
            if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000;
            m_MemSize = lngSize;
            if (strName.Length > 0)
            {
                //建立記憶體共享體(INVALID_HANDLE_VALUE)
                m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)lngSize, strName);
                if (m_hSharedMemoryFile == IntPtr.Zero)
                {
                    m_bAlreadyExist = false;
                    m_bInit = false;
                    return 2; //建立共享體失敗
                }
                else
                {
                    if (GetLastError() == ERROR_ALREADY_EXISTS)  //已經建立
                    {
                        m_bAlreadyExist = true;
                    }
                    else                                         //新建立
                    {
                        m_bAlreadyExist = false;
                    }
                }
                //---------------------------------------
                //建立記憶體映射
                m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_WRITE, 0, 0, (uint)lngSize);
                if (m_pwData == IntPtr.Zero)
                {
                    m_bInit = false;
                    CloseHandle(m_hSharedMemoryFile);
                    return 3; //建立記憶體映射失敗
                }
                else
                {
                    m_bInit = true;
                    if (m_bAlreadyExist == false)
                    {
                        //初始化
                    }
                }
                //----------------------------------------
            }
            else
            {
                return 1; //參數錯誤     
            }

            return 0;     //建立成功
        }
        /// <summary>
        /// 關閉共享記憶體
        /// </summary>
        public void Close()
        {
            if (m_bInit)
            {
                UnmapViewOfFile(m_pwData);
                CloseHandle(m_hSharedMemoryFile);
            }
        }

        /// <summary>
        /// 讀資料
        /// </summary>
        /// <param name="bytData">資料</param>
        /// <param name="lngAddr">起始位址</param>
        /// <param name="lngSize">個數</param>
        /// <returns></returns>
        public int Read(ref byte[] bytData, int lngAddr, int lngSize)
        {
            if (lngAddr + lngSize > m_MemSize) return 2; //超出資料區
            if (m_bInit)
            {               
                Marshal.Copy(m_pwData, bytData, lngAddr, lngSize);
            }
            else
            {
                return 1; //共享記憶體未初始化
            }
            return 0;     //讀成功
        }

        /// <summary>
        /// 寫資料
        /// </summary>
        /// <param name="bytData">資料</param>
        /// <param name="lngAddr">起始位址</param>
        /// <param name="lngSize">個數</param>
        /// <returns></returns>
        public int Write(byte[] bytData, int lngAddr, int lngSize)
        {
            if (lngAddr + lngSize > m_MemSize) return 2; //超出資料區
            if (m_bInit)
            {
                Marshal.Copy(bytData, lngAddr, m_pwData, lngSize);
            }
            else
            {
                return 1; //共享記憶體未初始化
            }
            return 0;     //寫成功
        }
    }
}           

測試例程:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ShareMemLib;

namespace YFShareMem
{
    public partial class frmShareMem : Form
    {
        ShareMem MemDB=new ShareMem();
        public frmShareMem()
        {
            InitializeComponent();
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (MemDB.Init("YFMemTest", 10240) != 0)
            {
                //初始化失敗
                MessageBox.Show("初始化失敗");
            }
            else
            {
                btnOpen.Enabled = false;
                chkWrite.Enabled = true;
                tmrTime.Enabled = true;
            }
        }

        private void tmrTime_Tick(object sender, EventArgs e)
        {
            byte[] bytData = new byte[16];
            int intRet = MemDB.Read(ref bytData, 0, 16);
            lstData.Items.Clear(); 
            if (intRet == 0)
            {
                for (int i = 0; i < 16; i++)
                {
                    lstData.Items.Add(bytData[i].ToString());
                }

                if (chkWrite.Checked)
                {
                    bytData[0]++;
                    bytData[1] += 2;
                    if (bytData[0] > 200) bytData[0] = 0;
                    if (bytData[1] > 200) bytData[1] = 0;
                    MemDB.Write(bytData, 0, 16);
                }
            }           
        }

    }
}