Я хочу вызвать скрипт python из моего кода на C++. Сценарий python выглядит так:C++ запускает скрипт (bash, python ...) и использует stdin/stdout для datatransfare [linux]
hello.py
#!/usr/bin/python
import sys
print "Hello!"
Readin = sys.stdin.read()
print Readin
Код C++ из другого вопроса из переполнения стека. Как это должно работать:
Создание пары труб.
Создание дочернего процесса с
fork()
.ребенок изгибает свои трубы до уровня stdin/stdout. Закрытие других концов и запуск сценария.
прослушивает трубы
read()
, принимает ввод. И после этого, , отправив сообщениеwrite()
.
Программа не возвращается из отцов линии, когда switch (readResult = read(childToPa...
вводится.
Я также не знаю, выполняет ли эта письменная часть свою работу. Является ли это многообещающей идеей делать это так, или есть другие рабочие возможности? thx!
Это выглядит следующим образом:
// maybe not all includes are necessary
#include <iostream>
#include <fstream>
#include <string>
#include <errno.h>
#include <sys/stat.h> // mkdir
#include <stdlib.h> // system()
#include <unistd.h> // rmdir
#include <cstring> // memset
// wait:
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int main() {
char target[] = "./hello.py";
enum PIPE_FILE_DESCRIPTERS {
READ_FD = 0, WRITE_FD = 1
};
enum CONSTANTS {
BUFFER_SIZE = 100
};
int parentToChild[2];
int childToParent[2];
pid_t pid;
string dataReadFromChild;
char buffer[BUFFER_SIZE + 1];
memset(buffer,0x00,BUFFER_SIZE + 1);
ssize_t readResult;
int status;
int retPipe1 = pipe(parentToChild);
int retPipe2 = pipe(childToParent);
switch (pid = fork()) {
case -1:
printf("Fork failed");
exit(-1);
case 0: /* Child will start scripts*/
{
// Bending stdin/out to the pipes?
int retdup21 = dup2(parentToChild[READ_FD], STDIN_FILENO);
int retdup22 = dup2(childToParent[WRITE_FD], STDOUT_FILENO);
int retdup23 = dup2(childToParent[WRITE_FD], STDERR_FILENO);
// Close in this Process the other sides of the pipe
int retclose1 = close(parentToChild[WRITE_FD]);
int retclose2 = close(childToParent[READ_FD]);
int retexe = execlp(target ," "); // warning not enough variable arguments to fit a sentinel [-Wformat=]
printf("This line should never be reached!!!"); // why? what happens if execlp finishes?
exit(-1);
break; // to make the compiler happy =)
}
default: /* Parent */
cout << "Child " << pid << " process running..." << endl;
// close the other ends of the pipe from the other process.
int retdup21 = close(parentToChild[READ_FD]);
int retdup22 = close(childToParent[WRITE_FD]);
// readtry
while (true) {
switch (readResult = read(childToParent[READ_FD], buffer, 1)) // execution does not return from this function.
{
case 0: /* End-of-File, or non-blocking read. */
{
cout << "End of file reached..." << endl << "Data received was (" << dataReadFromChild.size() << "):" << endl
<< dataReadFromChild << endl;
cout << "starting writing" << endl;
char bufferW[] = "{\"AElement\":\"Something\"}\0";
int writeResult = write(parentToChild[WRITE_FD],bufferW,sizeof(bufferW));
int saveerrno = errno;
if(-1 == writeResult)
{
cout << "errno while writing: " << errno << std::endl;
if (9 == saveerrno)
cout << "Errno Bad File descriptor" << endl;
}
cout << "Write Result: " << writeResult << std::endl;
int retWait = waitpid(pid, &status, 0);
cout << endl << "Child exit staus is: " << WEXITSTATUS(status) << endl << endl;
exit(0);
}
case -1:
{
if ((errno == EINTR) || (errno == EAGAIN)) {
errno = 0;
break;
} else {
printf("read() failed");
exit(-1);
}
}
default:
dataReadFromChild.append(buffer, readResult);
printf("%s",buffer);
memset(buffer,0x00,BUFFER_SIZE + 1);
break;
}
} /* while (true) */
} /* switch (pid = fork())*/
}
Во-первых, как это важно, что вы запустить код Python в другой программе? Ответ: Это не так. Таким образом, вы можете легко уменьшить свой код и вопрос, приблизившись к минимальному примеру. Однако, даже тогда, мне интересно, откуда у вас возникла идея подхода? Это не ново, не уникально и на самом деле хорошо установлено. Таким образом, должно быть тривиально найти существующие рабочие примеры! –
@ Ульрих Экхардт Сборка имеет ядро C++. Это получает вход для работы. Ядро готовит эту работу, обновляет базу данных и т. Д. После этого работа будет выполняться с помощью python. Ядро останется на будущее. Но вид работы, который предстоит сделать, изменится в будущем. Поэтому мы искали простой способ сделать это. Введите имя скриптового файла с API -> C++ prepare -> Python. Есть ли лучший способ сделать это? Я программист, и я не предпочитаю использовать этот хак. Поскольку эти сценарии должны быть вызваны друг другом, был предложен метод stdin/put. Лучшие идеи? Thx =) –