【问题标题】:Sharing two strings of data between processes in C++在 C++ 中的进程之间共享两个数据字符串
【发布时间】:2021-10-27 13:44:31
【问题描述】:

我最近遇到了一个问题,我有两个单独的进程需要共享两个字符串。 (一个动态 IP 地址和一个密钥)我习惯于使用 ROS,我会用两个字符串定义一个 ROS msg 并将其从一个字符串发送到另一个。

但是,我们在此处尝试使我们的应用程序尽可能简单,从而尽可能避免使用第三方软件。为此,我最初计划使用共享内存来发送一个同时包含 std::string 的结构,只是意识到这不是一个小问题,因为这个结构的大小是动态的......

我也想过使用其他方式,例如套接字或队列,但我总是遇到事先不知道这个结构的大小的问题。如何处理这个问题?有没有办法做到这一点,不涉及定义一些协议,在该协议中你在字符串前面加上它的大小并以空值或类似的结尾?

这是我的代码片段,它使用 Qt 创建一个 SharedMemory 来传递这个结构(当然没有成功)。


struct
{
   std::string ip_address;
   std::string key;
}server_data_t;
#define SERVER_DATA_LEN sizeof(server_data_t)


class SharedMemoryManager : public QSharedMemory
{
...
QByteArray SharedMemoryManager::read()
{
   QLOG_TRACE() << "SharedMemoryManager::read()";

   QByteArray readData;
   try
   {
      if(!isAttached())
         throw std::runtime_error("Share memory segment has not been opened yet");

      lock();
      readData = QByteArray(static_cast<char *>(data()), size());
      unlock();

      return readData;
   }
   catch (std::exception &e)
   {
      QLOG_ERROR() << e.what();

      return readData;
   }
}


void SharedMemoryManager::write(const QByteArray &byte_array)
{
   QLOG_TRACE() << "SharedMemoryManager::write()";

   try
   {
      if(!isAttached())
         throw std::runtime_error("Share memory segment has not been opened yet");

      lock();
      {
         auto *from = byte_array.data();
         char *to = static_cast<char*>(data());

         memcpy(to, from, qMin(size(), byte_array.size()));
      }
      unlock();
   }
   catch (std::exception &e)
   {
      QLOG_ERROR() << e.what();
   }
}

}

...

SharedMemoryManager _shm_manager;

server_data_t server_data;
server_data.ip_address = ...;
server_data.key = ...;

char *p = (char*)&server_data;

QByteArray byte_array = QByteArray(p, sizeof(server_data_t));

_shm_manager.write(byte_array);

...

SharedMemoryManager _shm_manager;
QByteArray byte_array = _shm_manager.read();

auto server_data = reinterpret_cast<server_data_t *>(byte_array.data());
std::cout << server_data->ip_address << std::endl;

当它试图访问字符串时失败了。

【问题讨论】:

    标签: c++ qt ros


    【解决方案1】:

    共享内存应该没问题(你甚至让 Qt 完成所有的工作) 您需要的可能是这样的,在您的共享内存中具有固定大小并且仍然有足够的空间来保存您的字符串。

    const std::size_t message_buf_size = 256;
    
    struct data_t
    {
       char message[message_buf_size]; // copy string into this and terminate with 0
       std::uint8_t ipv4[4];
    }
    

    请注意,字符串的数据无论如何都会分配在堆上(除了经过优化的小字符串),而不是在共享内存中。

    【讨论】:

      猜你喜欢
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      • 1970-01-01
      • 2010-11-15
      相关资源
      最近更新 更多