c++和c#之间的共享内存同步

Posted

技术标签:

【中文标题】c++和c#之间的共享内存同步【英文标题】:Shared memory synchronization between c++ and c# 【发布时间】:2016-10-25 10:44:13 【问题描述】:

我写了两个小程序。将字符串写入共享内存的 C++ 程序,以及从共享内存读取字符串并将其写入控制台的 C# 程序。

程序运行良好,但目前我在定时循环中写入字符串,然后以相同的频率从另一个定时循环中读取它。

我想做的是创建某种锁定。我想使用信号量/互斥体/任何东西,所以从 C# 我无法在 C++ 程序编写时读取 shm,反之亦然。

我读过一些名为 mutex 和 semamphore 的东西。我可以在两个程序中创建它们,但我真的不知道如何正确使用它们。

C++ 程序: MemoryWriter.h

#ifndef MEMORYWRITER_H_
#define MEMORYWRITER_H_

#include <windows.h>
#include <string>
#include <random>

class MemoryWriter 

public:

  MemoryWriter(const std::wstring& name, size_t size);
  std::string createRandomData() const;
  void write(const std::string& data);

private:

  char getRandomCharacter() const;
  void createSharedMemory();

private:

  std::wstring m_memoryName;
  size_t m_memorySize = 0;
  HANDLE m_shmHandler = 0;
;
#endif // !MEMORYWRITER_H_

MemoryWriter.cpp

#include "MemoryWriter.h"
#include <random>
#include <iostream>

///////////////////////////////////////////////////////////////////////////////
// USING SECTION                                                             //
///////////////////////////////////////////////////////////////////////////////

using std::string;

///////////////////////////////////////////////////////////////////////////////
// CONSTANTS SECTION                                                         //
///////////////////////////////////////////////////////////////////////////////

const char MinCharacter 'A' ;
const char MaxCharacter 'z' ;

///////////////////////////////////////////////////////////////////////////////
// PUBLIC SECTION                                                            //
///////////////////////////////////////////////////////////////////////////////

MemoryWriter::MemoryWriter(const std::wstring& name, size_t size) :
m_memoryName(name),
m_memorySize(size) 
  createSharedMemory();


string MemoryWriter::createRandomData() const 
  string data;
  for (size_t i = 0; i < m_memorySize; i++) 
    data += getRandomCharacter();
  
  return data;


void MemoryWriter::write(const string& data) 
  if (!m_shmHandler) 
    return;
  
  auto buffer = MapViewOfFile(m_shmHandler, FILE_MAP_ALL_ACCESS, 0, 0, m_memorySize);
  if (NULL == buffer) 
    std::cerr << "Cannot use MapViewOfFile: null buffer." << std::endl;
    return;
  
  CopyMemory(buffer, data.c_str(), data.size());


//////////////////////////////////////////////////////////////////////////////
// PRIVATE SECTION                                                          //
//////////////////////////////////////////////////////////////////////////////

char MemoryWriter::getRandomCharacter() const 
  return MinCharacter + rand() % 24;


void MemoryWriter::createSharedMemory() 
  m_shmHandler = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, m_memoryName.c_str());

  if (!m_shmHandler) 
    m_shmHandler = CreateFileMapping(
      INVALID_HANDLE_VALUE,
      NULL,
      PAGE_READWRITE,
      0,
      m_memorySize,
      m_memoryName.c_str());
  

main.cpp

#include "MemoryWriter.h"
#include <iostream>
#include <string>
#include <thread>

int main(int argc, char* argv[])

  std::wstring memoryName L"shm_1" ;
  size_t memorySize 80 ;
  MemoryWriter writer(memoryName, memorySize);

  while (true) 
    std::string data;
    data = writer.createRandomData();
    writer.write(data);
    std::cout << "C++: Written in shm - " << data << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  

  return 0;

C#程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SharedMemoryReader

    class Program
    
        static void Main(string[] args)
        
            string shmName = "shm_1";
            int shmSize = 80;
            var shm = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateOrOpen(shmName, shmSize);
                while (true)
                
                    var view = shm.CreateViewStream();
                    if (view == null)
                    
                        continue;
                    
                    byte[] data = new byte[shmSize];
                    view.Read(data, 0, shmSize);
                    string text = System.Text.Encoding.Default.GetString(data);
                    System.Console.WriteLine("C#: Read from shm - " + text);
                    System.Threading.Thread.Sleep(100);
                
        
    

【问题讨论】:

搜索并了解Windows 上的命名信号量。有许多可用的教程和参考资料。 【参考方案1】:

您将需要一个命名的同步对象。也许是mutex。

在 C++ 中,您可以调用 CreateMutex,而在 C# 中,Mutex 类会为您处理它。

两个链接都附有示例,如果遇到具体问题,不妨试试看。

【讨论】:

【参考方案2】:

我建议使用 named 信号量或 named 互斥量...命名对象是系统范围的

来自 MSDN Interprocess Synchronization:

命名对象为进程共享对象提供了一种简单的方法 把手

【讨论】:

以上是关于c++和c#之间的共享内存同步的主要内容,如果未能解决你的问题,请参考以下文章

在两个应用程序之间共享内存

C++ 和 Java 进程之间的共享内存

C++ 线程之间的内存共享

使用信号量进行共享内存同步

c# 通过内存映射实现文件共享内存

如何使用共享内存在 cpp 和 python 之间共享 cv::Mat 以进行处理