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

时间:2013-02-12 19:02:27

标签: c++ system ipc pipe

在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()

6 个答案:

答案 0 :(得分:0)

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

在Linux上,如果要访问子项的stdin或stdout,可以使用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);
}

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您可以使用pipes进行通信。提供的链接有linux的例子,但它与你为windows编写的内容非常相似。

如果您需要发送可能在运行时更改的任意数据,您可以考虑序列化通过管道发送的数据并在接收器上对其进行反序列化。您可以使用XML,JSON或Protobuf之类的东西。如果您使其具有人类可读性,则可以使用eyeball mark 1

添加重用组件或调试正在发生的事情的机会

答案 5 :(得分:0)

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

“翻译”

#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;
}

“dictionary.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

在我把它打开之前,我还有一些要做的事情,但这就是它的要点。谢谢你们!