简体   繁体   English

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

[英]C++ application notify C# application

I'm currently having a C++ app and a C# app, I want my C++ app notify C# app that something is happended (like events), what I'm doing now is using shared memory like:我目前有一个 C++ 应用程序和一个 C# 应用程序,我希望我的 C++ 应用程序通知 C# 应用程序发生了某些事情(例如事件),我现在正在使用共享内存,例如:

C++:
CreateFileMappingW(L"MySharedMemory");

C#:
MemoryMappedFile.OpenExisting("MySharedMemory")

so C++ app write a flag in shared memory then C# app read this flag and know something is happened, but it is a bad idea because C# app have to keep checking the flag, so is there a better idea?所以 C++ 应用程序在共享内存中写入一个标志,然后 C# 应用程序读取这个标志并知道发生了一些事情,但这是一个坏主意,因为 C# 应用程序必须不断检查标志,所以有更好的主意吗?

This is a very wide topic called inter-process communication: https://en.wikipedia.org/wiki/Inter-process_communication这是一个非常广泛的主题,称为进程间通信: https : //en.wikipedia.org/wiki/Inter-process_communication

The details greatly depend on the OS you're targeting.详细信息在很大程度上取决于您的目标操作系统。 Eg for MS Windows you can find a list of options at https://docs.microsoft.com/en-us/windows/desktop/ipc/interprocess-communications例如,对于 MS Windows,您可以在https://docs.microsoft.com/en-us/windows/desktop/ipc/interprocess-communications找到选项列表

Ok, sorry if it's a bit messy or badly written, it's some legacy I edited some time ago and yes I know, I wasn't following naming standards, shame on me ^^好吧,对不起,如果它有点乱或写得不好,这是我前段时间编辑的一些遗产,是的,我知道,我没有遵循命名标准,对我感到羞耻^^

I'll let you clean and take what you need.我会让你打扫干净,拿走你需要的东西。 Just for context, in my case the C++ app is creating the named pipe and each time writes "'size of the code'-'code''potentially some crap'" where code is an alphanumeric code I needed to retrieve almost in real time.仅就上下文而言,在我的情况下,C++ 应用程序正在创建命名管道,并且每次写入“'代码的大小'-'代码''可能是一些废话'”,其中代码是我需要几乎实时检索的字母数字代码.

Here is the class handling most of the named pipe processing:这是处理大部分命名管道处理的类:

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();
    }
  }
}

Then I used it this way:然后我是这样用的:

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();

Hope it helps ;)希望能帮助到你 ;)

EDIT (in case you need the C++ part, I just found it back):编辑(如果您需要 C++ 部分,我刚刚找到了它):

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM