2016-10-25 48 views
0

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

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

我想要做的是创建某种锁定。我想使用信号量/互斥量/任何,所以从C#我无法读取SHM,而C++程序正在写它,反之亦然。

我读过类似命名互斥和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); 
       } 
     } 
    } 
} 
+0

在Windows *上搜索并阅读*命名的信号量。有许多教程和参考可用。 –

回答

1

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

在C++中,您可以拨打CreateMutex,而在C#中有Mutex类可以为您处理它。

两个链接都带有示例,如果遇到特定问题,可以试试并返回。

+0

谢谢我发现了一些关于那个教程.... – Jepessen

1

我会建议使用命名旗语或命名互斥......指定对象是整个系统的

从MSDN Interprocess Synchronization

命名对象的过程提供一种简单的方法共享对象 句柄