[英]Shared memory synchronization between c++ and c#
I've written two little programs.我写了两个小程序。 A C++ program that writes a string in a shared memory, and a C# program that reads the string from shared memory and writes it on the console.
在共享内存中写入字符串的 C++ 程序,以及从共享内存中读取字符串并将其写入控制台的 C# 程序。
Programs work well, but at the moment I write the string in a timed loop, and I read it from another timed loop, with same frequency.程序运行良好,但目前我在定时循环中写入字符串,然后从另一个定时循环中以相同的频率读取它。
What I want to do is to create some sort of locking.我想要做的是创建某种锁定。 I want to use a semaphore/mutex/whatever, so from C# I cannot read shm while C++ program is writing it, and viceversa.
我想使用信号量/互斥量/任何东西,所以从 C# 我无法在 C++ 程序编写时读取 shm,反之亦然。
I've read something like named mutex and semamphore.我读过类似命名互斥锁和信号灯的内容。 I can create them in both programs, but I really don't know how to use them properly.
我可以在两个程序中创建它们,但我真的不知道如何正确使用它们。
C++ program: MemoryWriter.h 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# program 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);
}
}
}
}
You will need a named synchronization object.您将需要一个命名的同步对象。 Maybe a mutex .
也许是互斥锁。
In C++ you can call CreateMutex while in C# there is the Mutex class that handles it for you.在 C++ 中,您可以调用CreateMutex,而在 C# 中,有Mutex类为您处理它。
Both links come with examples, maybe you give it a try and come back if you encounter a specific problem.两个链接都带有示例,也许您可以尝试一下,如果遇到特定问题,请返回。
I would suggest to use named semaphore or named mutex... named objects are system-wide我建议使用命名信号量或命名互斥锁...命名对象是系统范围的
from MSDN Interprocess Synchronization :来自 MSDN进程间同步:
Named objects provide an easy way for processes to share object handles
命名对象为进程共享对象句柄提供了一种简单的方法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.