代码之家  ›  专栏  ›  技术社区  ›  DaveG

C++应用程序通知C++应用程序

  •  2
  • DaveG  · 技术社区  · 7 年前

    我现在有一个C++应用程序和一个C应用程序,我希望我的C++应用程序通知C应用程序有什么事情发生了(比如事件),我现在正在使用的是共享内存:

    C++:
    CreateFileMappingW(L"MySharedMemory");
    
    C#:
    MemoryMappedFile.OpenExisting("MySharedMemory")
    

    所以C++应用程序在共享内存中写一个标志,然后C应用程序读取这个标志,知道发生了什么,但是这是个坏主意,因为C应用程序必须不断检查标志,所以有更好的主意吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Mikitori    7 年前

    好吧,抱歉,如果写得有点乱或者写得不好,那是我前段时间编辑的一些遗产,是的,我知道,我没有遵循命名标准,真丢人^^

    下面是处理大多数命名管道处理的类:

    using System;
    using System.Collections.Generic;
    using Microsoft.Win32.SafeHandles;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.IO;
    
    namespace NamedPipe
    {
        public class NamedPipeServer
        {
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern SafeFileHandle CreateNamedPipe(
           String sPipeName,
           uint dwOpenMode,
           uint dwPipeMode,
           uint nMaxInstances,
           uint nOutBufferSize,
           uint nInBufferSize,
           uint nDefaultTimeOut,
           IntPtr lpSecurityAttributes);
    
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern int ConnectNamedPipe(SafeFileHandle hNamedPipe, IntPtr lpOverlapped);
    
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern int DisconnectNamedPipe(SafeFileHandle hNamedPipe);
        public const uint DUPLEX = (0x00000003);
        public const uint FILE_FLAG_OVERLAPPED = (0x40000000);
        public List<string> m_ReceivedValues = new List<string>();
    
        public class Client
        {
            public SafeFileHandle handle;
            public FileStream stream;
        }
    
        public const int BUFFER_SIZE = 100;
        public Client m_clientse = null;
        public string m_sPipeName;
        Thread m_listenThread;
        SafeFileHandle m_clientHandle;
    
        public NamedPipeServer(string PName)
        {
            m_sPipeName = PName;
        }
    
        public void Start()
        {
            m_listenThread = new Thread(new ThreadStart(ListenForClients));
            m_listenThread.Start();
        }
        private void ListenForClients()
        {
            while (true)
            {
                m_clientHandle = CreateNamedPipe(m_sPipeName, DUPLEX | FILE_FLAG_OVERLAPPED, 0, 255, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
                if (m_clientHandle.IsInvalid)
                    return;
    
                int success = ConnectNamedPipe(m_clientHandle, IntPtr.Zero);
                if (success == 0)
                    return;
    
                m_clientse = new Client();
                m_clientse.handle = m_clientHandle;
                m_clientse.stream = new FileStream(m_clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
    
                Thread readThread = new Thread(new ThreadStart(Read));
                readThread.Start();
            }
        }
        private void Read()
        {
            byte[] buffer = null;
            ASCIIEncoding encoder = new ASCIIEncoding();
    
            while (true)
            {
                int bytesRead = 0;
                try
                {
                    buffer = new byte[BUFFER_SIZE];
                    bytesRead = m_clientse.stream.Read(buffer, 0, BUFFER_SIZE);
                }
                catch
                {
                    //read error has occurred
                    break;
                }
    
                //client has disconnected
                if (bytesRead == 0)
                    break;
    
                int ReadLength = 0;
                for (int i = 0; i < BUFFER_SIZE; i++)
                {
                    if (buffer[i].ToString("x2") != "cc")
                    {
                        ReadLength++;
                    }
                    else
                        break;
                }
                if (ReadLength > 0)
                {
                    byte[] Rc = new byte[ReadLength];
                    Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
                    string sReadValue = encoder.GetString(Rc, 0, ReadLength);                    
                    string[] codeInfo = sReadValue.Split('-');
                    if (codeInfo.Length == 2)
                    {
                        string sSize = codeInfo[0];
                        string sCode = codeInfo[1];
                        string sFinalValue = sCode;
                        int nSize = Int32.Parse(sSize);
                        if (sCode.Length >= nSize)
                        {
                            sFinalValue = sCode.Substring(0, nSize);
                        }
                        m_ReceivedValues.Add(sFinalValue);
                        Console.WriteLine($"C# App: Received value : {sFinalValue}");
                        buffer.Initialize();
                    }
                    else
                    {
                        Console.WriteLine("C# App: Received value in named pipe is badly formatted (we expect 'size-code')");
                    }
                }
            }
            m_clientse.stream.Close();
            m_clientse.handle.Close();
        }
    
        public void StopServer()
        {
            DisconnectNamedPipe(m_clientHandle);
            m_listenThread.Abort();
        }
      }
    }
    

    然后我用这种方式:

    NamedPipeServer m_pPipeServer = null;
    [...]
    m_pPipeServer = new NamedPipeServer(@"\\.\pipe\myPipe");
    m_pPipeServer.Start();
    [...]
    if (m_pPipeServer != null)
    {
      if (m_pPipeServer.m_ReceivedValues.Count > 0)
      {
        string sLastReceivedValue = m_pPipeServer.m_ReceivedValues.ElementAt(0);
        [...]
        m_pPipeServer.m_ReceivedValues.RemoveAt(0);
      }
    }
    [...]
    m_pPipeServer.StopServer();
    

    希望有帮助;)

    HANDLE  m_hDemoPipe;
    m_hDemoPipe = CreateFile("\\\\.\\pipe\\myPipe", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    
    [...]
    
    char buf[100];
    CString sValue;
    USES_CONVERSION;
    sValue.Format(_T("%ld-%s"), sMsg.GetLength(), sMsg);
    CStringA sValueAnsi = T2A(sValue);
    for (int i = 0; i < sValueAnsi.GetLength(); ++i)
    {
        buf[i] = static_cast<char>( sValueAnsi.GetAt(i) );
    }
    DWORD cbWritten;
    DWORD dwBytesToWrite = (DWORD)strlen(buf);
    WriteFile(m_hDemoPipe, buf, dwBytesToWrite, &cbWritten, NULL);
    
    [...]
    
    CloseHandle(m_hDemoPipe);
    
    推荐文章