如何在进程C ++之间发送std :: string数组

Posted

技术标签:

【中文标题】如何在进程C ++之间发送std :: string数组【英文标题】:How to send std::string array between processes C++ 【发布时间】:2013-02-12 19:02:27 【问题描述】:

在 C++ 中,我需要从一个主程序启动一个辅助程序,向第二个程序发送一些参数。我需要将辅助程序产生的数据返回给主程序。在这种情况下,数据恰好是一个二维 std::string 数组;我们称之为stringArray。这很容易做到:

// snippet from Primary
std::string executionString ("./secondaryProgram arg1 arg2 arg3");
system(executionString);

我不知道如何将辅助程序生成的数据返回给主程序(从辅助程序写入临时文件然后从主程序读取文件)。

换句话说,如果我能做这样的事情会很棒:

// snippet from Primary
std::string stringArray[2][3];  
stringArray = system(executionString);

我不希望任何人提供如此简单的解决方案或工作代码,任何朝着正确方向的推动都将受到赞赏。

我不能为此目的使用套接字。我无法弄清楚如何在 std::cout 和 std::cin 之间构建适用于这种情况的管道。我唯一真正的限制是我的解决方案以某种方式涉及system()

【问题讨论】:

“我不能为此目的使用套接字。”为什么? 为什么您的解决方案必须涉及system 这个问题有问题。 “如何通过 sockets 发送……?” +“我不能使用套接字”+“我的解决方案[必须]涉及system()”=? @leemes,谢谢。老实说,我不记得写过那个,但我想我一定有。编辑标题。 没问题。认为 ;) 教授是否认为必须使用 system() 对子进程的 stdin / stdout 进行读写? 【参考方案1】:

system() 不会为子进程创建管道。子进程继承父进程的标准输入、标准输出和标准错误描述符。

在 Linux 上,如果您想访问孩子的标准输入或标准输出,可以使用 popen()

既然你必须使用system(),你可以 让辅助程序将其结果存储在文件中。然后,您的主程序将在系统完成后打开该文件。有点像这样:

std::string executionString ("./secondaryProgram arg1 arg2 arg3 > output_file.txt");
system(executionString);
std::ifstream result("output_file.txt");
while( result >> str) 
  result_vector.push_back(str);

【讨论】:

你确定system支持shell语法吗? 他明确表示他不是在寻找这个解决方案。 @JonBentley 他特别说他必须使用 system() @leemes - 是的。字符串交给sh -c 我提到了这个解决方案,并暗示它在我的 OP 中不是一个令人满意的解决方案(我承认这可能是 TL;DR)。我需要将信息直接从一个进程发送到另一个进程。如果我必须将我的 std::string 数组分解成更原始的东西也没关系,我只是想要能够发送一条数据并完成它的简单性。【参考方案2】:

看看boost.interprocess。它包含许多可用于 IPC 的便携实用程序。

如果您不想依赖 boost,可以执行this 之类的操作。使用 C++11 模式和-pthread GCC 选项编译。

【讨论】:

【参考方案3】:

为什么不将第二个进程中的相关信息写入一个文件,然后在第一个进程中读取该文件。这样做似乎很奇怪,但我认为它符合您教授的标准,至少是您与我们分享的部分。

【讨论】:

【参考方案4】:

Boost Interprocess 应该适合你。它支持不同进程的线程之间的消息队列。

【讨论】:

【参考方案5】:

您可以使用pipes 进行交流。提供的链接有 linux 的示例,但它与您为 windows 编写的非常相似。

如果您需要发送可能在运行时发生变化的任意数据,您可以考虑对通过管道发送的数据进行序列化并在接收器处对其进行反序列化。您可以使用 XML、JSON 或类似 Protobuf 的东西。如果您使其具有人类可读性,则增加了重用组件或使用eyeball mark 1调试正在发生的事情的机会

【讨论】:

【参考方案6】:

好吧,这就是我最终要做的。

“翻译”

#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cstdlib>
#include <unistd.h>

std::vector<std::string> sortTerms(int n, char* argv[]) 
  std::vector<std::string> sortedTerms (n);

  for (int i = 0; i < n; i++) 
sortedTerms[i] = argv[i+1]; // first term argv is program name
  

  std::sort(sortedTerms.begin(),sortedTerms.end());

  return sortedTerms;


std::vector<std::string> splitString(int n,std::string str) 
  std::vector<std::string> stringVector (n);

  std::istringstream iss(str);

  for (int i = 0; i < n; i++) 
std::getline(iss, stringVector[i], ' ');

  return stringVector;


int main(int argc, char** argv) 
  const int NUM_TERMS = (argc - 1); // number of words to translate
  std::string output[NUM_TERMS][2]; // used to store a translated word alongside the English equivalent
  std::string stringBuffer; // used to start dictionary with arguments
  std::vector<std::string> stringVector (NUM_TERMS); // used as a buffer
  std::ofstream outputFile("translated.txt"); // file to write translations to
  const bool VERBOSE = true;

  stringBuffer.clear();
  stringBuffer.append("./dictionary ");

  // Sort English words and load them into output
  stringVector = sortTerms(NUM_TERMS, argv);
  for (int i = 0; i < NUM_TERMS; i++) 
output[i][0] = stringVector[i];
stringBuffer = stringBuffer.append(stringVector[i]);
stringBuffer = stringBuffer.append(" ");
  

  int pipeStatus;
  int pipeOutput[2]; // file descriptor

  pipeStatus = pipe(pipeOutput); // create output read/write pipe ends
  if (pipeStatus < 0) 
std::cerr << "ERROR CREATING PIPE" << std::endl;
exit(1);
  

  int pid = 0;
  pid = fork();

  if (pid == 0)  // dictionary
// Connect the pipes
dup2 (pipeOutput[1],1);

// Execute the program
system(stringBuffer.c_str());

// Close pipes
close(pipeOutput[0]);
close(pipeOutput[1]);

exit(0);
  
  else if (pid > 0)  // Original process
char* buffer = new char[1024]; // input buffer

// Receive string from dictionary
read(pipeOutput[0],buffer,1024); // read in from output of dictionary

stringBuffer = buffer; // I'd rather work with a std::string

stringVector = splitString(NUM_TERMS, stringBuffer);
for (int i = 0; i < NUM_TERMS; i++)
  output[i][1] = stringVector[i];

// Close pipes
close(pipeOutput[0]);
close(pipeOutput[1]);

if (VERBOSE) 
  for (int i = 0; i < NUM_TERMS; i++)
    std::cout << output[i][0] << " -> " << output[i][1] << std::endl;


// write translationString to file
for (int i = 0; i < NUM_TERMS; i++) 
  outputFile.write(output[i][0].c_str(),output[i][0].length());
  outputFile.write(" -> ",4);
  outputFile.write(output[i][1].c_str(),output[i][1].length());
  outputFile.write("\n",1);
 

outputFile.close();

exit(0);
  
  else if (pid == -1) 
std::cerr << "ERROR FORKING PROCESS" << std::endl;
exit(1);
  
  return 0;

“字典”

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

std::vector<std::string> splitString(std::string str)

  std::vector<std::string> stringVector (2);

  std::istringstream iss(str);

  std::getline(iss, stringVector[0], ' ');
  std::getline(iss, stringVector[1], ' ');

  return stringVector;


int main(int argc, char* argv[])   
  const int NUM_TERMS = (argc - 1);
  std::string stringBuffer;
  std::string returnString[NUM_TERMS];
  std::vector<std::string> stringVector;
  std::ifstream dictionaryFile ("./dictionary.txt");

  // There must be at least one arguement
  if (argc <= 1)
std::cout << "Nothing to translate..." << std::endl;

  for (int i = 0; i < NUM_TERMS; i++) 
while (dictionaryFile) 
  getline(dictionaryFile,stringBuffer);  
  stringVector = splitString(stringBuffer);
  if (stringVector[0] == argv[i+1])  // wut
    returnString[i] = stringVector[1];
    break;
  

  

  // clear string buffer
  stringBuffer.clear();

  // Form translated words string
  for (int i = 0; i < NUM_TERMS; i++) 
    stringBuffer.append(returnString[i]);
    if (i < (NUM_TERMS - 1))
        stringBuffer.append(" "); // append a space after each but the last term
  

  // print translated words
  std::cout << stringBuffer << std::endl;

  dictionaryFile.close();

  return 0;

“字典.txt”

Apple Apfel
Banana Banane
Blackberry Brombeere
Blueberry Heidelbeere
Cherry Kirsche
Fruit Obst
Grape Traube
Lemon Zitrone
Lime Limone
Orange Orange
Peach Pfirsich
Pear Birne
Plum Zwetschge
Raspberry Himbeere
Strawberry Erdbeere

打算像$ ./dictionary Apple Orange Strawberry一样运行

产生“translated.txt”

Apple -> Apfel
Orange -> Orange
Strawberry -> Erdbeere

在上交之前,我还有一些润色工作要做,但这就是要点。谢谢大家!

【讨论】:

以上是关于如何在进程C ++之间发送std :: string数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在Linux上的c中的父进程和子进程之间进行乒乓球

如何使用 python 信号在独立进程之间发送消息?

如何在父进程和子进程之间发送带有 pipe() 的矩阵?

Twisted - 如何创建多协议进程并在协议之间发送数据

多个进程之间的消息传递,每个进程在 c 中有许多线程

如何在 c 中使用 posix 命名信号量和 Linux 上两个进程之间的共享内存?