Есть ли у нас что-то похожее на IPC::Open3 perl в C или C++?

Я использовал open3 perl для запуска команды, пользовательская команда ведет себя как оболочка, она принимает ввод и отображает вывод и ждет другого ввода, пока не будет дан выход

Теперь я должен использовать ту же команду и написать ее на языке C. Есть ли у нас что-то похожее на IPC::Open3 на C или C++?


person learner    schedule 18.01.2018    source источник
comment
pipe() и fork() могут делать то же самое, но, конечно, они намного громоздче. Начните с чтения Открытий безопасных каналов в perldoc perlipc, что является сравнительно высоким -уровень обсуждения этих понятий. Затем вы можете перенести те же концепции в Posix/C.   -  person amon    schedule 18.01.2018
comment
Да, я смотрел на трубу и вилку, но я не могу заставить ее работать, и это выходит за рамки моего понимания, я думаю, потребуется некоторое время, чтобы справиться с этим.   -  person learner    schedule 18.01.2018
comment
На С или на С++? Это не одно и то же. Винда или линукс?   -  person zdim    schedule 18.01.2018
comment
Короче говоря: system проще всего, но может быть небезопасным (и не дает всего, что делает Open3); popen лучше, как и fork+exec. Я не уверен, что IPC::Open3 указывает только на Linux (не знаю, является ли он переносимым), но: в Windows для этого есть API, CreateProcess в первую очередь, а затем ShellExecute (возможно, больше)   -  person zdim    schedule 18.01.2018
comment
Если вы можете использовать boost, то boost::process, вероятно, стоит взгляд.   -  person G.M.    schedule 18.01.2018
comment
open3 — это просто набор системных вызовов. Было бы тривиально портировать на C.   -  person ikegami    schedule 18.01.2018
comment
@learner: Пожалуйста, ответьте на вопрос zdim о том, работаете ли вы над Windows или Linux (или чем-то другим).   -  person Borodin    schedule 18.01.2018
comment
@Borodin: я на POSIX, если быть точным, RHEL   -  person learner    schedule 24.01.2018


Ответы (1)


popen() поддерживает одностороннюю связь. Если вы хотите двунаправленный обмен данными, вам понадобятся 2 канала. Джефф Эплер придумал следующий двунаправленный popen2.c реализация:

#include <sys/types.h>
#include <unistd.h>

struct popen2 {
    pid_t child_pid;
    int   from_child, to_child;
};

int popen2(const char *cmdline, struct popen2 *childinfo) {
    pid_t p;
    int pipe_stdin[2], pipe_stdout[2];

    if(pipe(pipe_stdin)) return -1;
    if(pipe(pipe_stdout)) return -1;

    printf("pipe_stdin[0] = %d, pipe_stdin[1] = %d\n", pipe_stdin[0], pipe_stdin[1]);
    printf("pipe_stdout[0] = %d, pipe_stdout[1] = %d\n", pipe_stdout[0], pipe_stdout[1]);

    p = fork();
    if(p < 0) return p; /* Fork failed */
    if(p == 0) { /* child */
        close(pipe_stdin[1]);
        dup2(pipe_stdin[0], 0);
        close(pipe_stdout[0]);
        dup2(pipe_stdout[1], 1);
        execl("/bin/sh", "sh", "-c", cmdline, 0);
        perror("execl"); exit(99);
    }
    childinfo->child_pid = p;
    childinfo->to_child = pipe_stdin[1];
    childinfo->from_child = pipe_stdout[0];
    return 0; 
}

#define TESTING
#ifdef TESTING
int main(void) {
    char buf[1000];
    struct popen2 kid;
    popen2("tr a-z A-Z", &kid);
    write(kid.to_child, "testing\n", 8);
    close(kid.to_child);
    memset(buf, 0, 1000);
    read(kid.from_child, buf, 1000);
    printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0)); 
    printf("from child: %s", buf); 
    printf("waitpid() -> %d\n", waitpid(kid.child_pid, NULL, 0));
    printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0)); 
    return 0;
}
#endif
person Laszlo    schedule 18.01.2018
comment
Хотя эти ссылки могут ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. - person Gerhard; 18.01.2018
comment
Герхард Барнард, о чем вы? Попробуйте popen() - это важная часть. :) Кроме того, я боюсь, что спецификации popen() существенно не изменятся в ближайшее время, и я не верю, что эти ссылки скоро перестанут работать. По крайней мере, до тех пор, пока «ученик» не получит возможность нажать на них. В любом случае, я надеюсь, что приведенные примеры не вызовут новых стереотипных реакций. - person Laszlo; 18.01.2018
comment
спасибо за внимание, но я уже знаю это, то, что я искал, можно рассматривать как двунаправленную связь, например, popen2 дает дескрипторы входных и выходных файлов? Я думаю, в C или CPP ничего подобного нет. - person learner; 18.01.2018
comment
@Laszlo, мы работаем над обзором, который основан на положениях и условиях SO, мы не публикуем ответы только по ссылкам, и изначально пост был помечен как низкокачественный из-за ответа только по ссылке. Если бы вы впоследствии получили 4 голоса за удаление, он был бы удален, поэтому комментарий был опубликован. После редактирования должно быть нормально. - person Gerhard; 18.01.2018
comment
@learner, да, вам нужно будет использовать 2 канала, так как они однонаправленные. - person Laszlo; 18.01.2018
comment
@learner Я нашел несколько реализаций popen2 здесь, в stackoverflow ( stackoverflow.com/questions/12778672/), и один здесь: media.unpythonic.net/emergent-files/01108826729/popen2.c . Это помогает? - person Laszlo; 18.01.2018