URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 5393
[ Назад ]

Исходное сообщение
"Вызов внешней программы "

Отправлено Flex25 , 05-Май-06 08:54 
Нужно в Unix из программы C++ вызвать интерпретатор Perl (/usr/local/perl), передать ему программный код на языке Perl и получить результат выполенения Perl-программы.

Как это можно сделать? Это вроде через переключение потоков делается, но нигде не могу инфы по этому найти :(

Помогите!


Содержание

Сообщения в этом обсуждении
"Вызов внешней программы "
Отправлено DeadMustdie , 05-Май-06 09:38 
>не могу инфы по этому найти :(

RTFM:
man 2 pipe
man 2 dup2
man 2 fork
man 2 exec

А еще можно книжку купить. Про программирование в системе UNIX. Почти любую.


"Вызов внешней программы "
Отправлено Flex25 , 05-Май-06 10:08 
>А еще можно книжку купить. Про программирование в системе UNIX. Почти любую.

Не мог бы дать пример, а то мне уже сегодня это нужно... Горю... :(


"Вызов внешней программы "
Отправлено Spirit , 05-Май-06 13:25 
>Нужно в Unix из программы C++ вызвать интерпретатор Perl (/usr/local/perl), передать ему
>программный код на языке Perl и получить результат выполенения Perl-программы.
>
>Как это можно сделать? Это вроде через переключение потоков делается, но нигде
>не могу инфы по этому найти :(
>
>Помогите!

чтото типа:
#define PERLPATH "/usr/local/perl"

FILE result = popen(PERLPATH, "w");
if(!result)
{
  printf("Все плохо\n");
}
else
{
  //читаешь из потока
  char *s[100];
  fscanf(result, "%s", s);
}
//тока учти что popen либо для чтения либо для записи открывет файл
//если открыл для чтения, то запущеный процесс при попытке прочесть с клавы из stdin //твоего процесса читать будет
P.S. извиняюсь за возможные ошибки лучше прочитай про popen


"Вызов внешней программы "
Отправлено Flex25 , 06-Май-06 20:22 
>//тока учти что popen либо для чтения либо для записи открывет файл
>//если открыл для чтения, то запущеный процесс при попытке прочесть с клавы

Да, в том-то и дело...

Мне нужно-то сделать следующее:
1. Открыть через вою прогу интерпретатор /usr/local/perl
2. Передать ему код своей perl-программы
3. Получить от него результат выполнения этой perl-программы
4. Вывести этот результат в stdout.

А т.к. POPEN может быть открыт только для чтения ИЛИ записи (а не одновреиенно для чтения и записи), то я не смогу с помощью popen сначала записать, а потом сразу же прочитать данные из /usr/local/perl.

А как такую проблему решить?


"Вызов внешней программы "
Отправлено Spirit , 08-Май-06 21:56 
>А т.к. POPEN может быть открыт только для чтения ИЛИ записи (а
>не одновреиенно для чтения и записи), то я не смогу с
>помощью popen сначала записать, а потом сразу же прочитать данные из
>/usr/local/perl.
>
>А как такую проблему решить?

я с этим продолбался день и забил, мне просто не суть важно было как параметры передавать
но перлу можно ведь в качастве параметра передать имя файла, это проще гараздо
а в С точно знаю есть функции для генерации неповторимых имен файлов(ну чтоб в темпы складывать и юзать временно:)

я попытаюсь пример дать, но он что-то на самом деле не совсем хорошо работал
там одна прога запускала 2 другие и перед exec-ом их стандартные потоки перенаправляла друг другу:)


"Вызов внешней программы "
Отправлено Flex25 , 11-Май-06 00:01 
>я с этим продолбался день и забил, мне просто не суть важно
>было как параметры передавать
>но перлу можно ведь в качастве параметра передать имя файла, это проще
>гараздо
>а в С точно знаю есть функции для генерации неповторимых имен файлов(ну
>чтоб в темпы складывать и юзать временно:)
>
>я попытаюсь пример дать, но он что-то на самом деле не совсем
>хорошо работал
>там одна прога запускала 2 другие и перед exec-ом их стандартные потоки
>перенаправляла друг другу:)

Спасибо за попытку решить эту проблему. Хорошо бы, если бы вы выложили на форуме пример этой проги, которая останавливает связь с другими.

В результате же изучения мануалов я пришел к следующим неутешительным выводам:
- fork() создает процесс-потомок, который аналдогичен процессу-родителю. Через fork() я не могу вызвать стороннюю программу.
- pipe() делает возможность ввода/вывода между процессами, но этот ввов вывод возможет только после fork(). А как мне pipe() сделать для внешней программы, а не для копии самой себя?
- popen() открывает стороннюю программу, но устанавливает с ней только одностороннюю связь (чтение или запись), а мне нужна двусторонняя.

Что же делать-то? Где я не прав? В каких мануалах достать пример необходимой мне проги?


"Вызов внешней программы "
Отправлено gyn61 , 11-Май-06 00:57 
И чему только в школе учат?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  int p1[2], p2[2];
  FILE *f1, *f2;
  int i;
  char line[80];
  pipe(p1);
  pipe(p2);
  f1 = fdopen(p1[1], "w");
  f2 = fdopen(p2[0], "r");
  if (fork() == 0) {
    dup2(p1[0], 0); // stdin
    dup2(p2[1], 1); // stdout
    close(p1[1]);
    close(p2[0]);
    execlp("sort", "sort", NULL);
  } else {
    close(p1[0]);
    close(p2[1]);
  }
  for (i = 0; i < 10; i ++) {
    fprintf(f1, "%d\n", random());
  }
  fclose(f1);
  while (fgets(line, sizeof(line), f2) != NULL) {
    printf("Строка: %s", line);
  }
  return 0;
}


"Вызов внешней программы "
Отправлено Flex25 , 11-Май-06 21:10 
>И чему только в школе учат?

Но опять же это совсем те тот пример, который нужен :(

Через FORK() вы создаете копию своей же программы и передаете данные между родителем и потомком с помощью файла.

А мне не надо установить двухстороннюю связь с программой /usr/bin/perl, т.е. эта сторонняя программа - она же не мой потомок. Как такое сделать? Как подключить эти самые пайпы не к своему потомку, а к вызываемой мною сторонней проге???


"Вызов внешней программы "
Отправлено gyn61 , 11-Май-06 22:31 
>Но опять же это совсем те тот пример, который нужен :(

См. ниже

>Через FORK() вы создаете копию своей же программы и передаете данные между
>родителем и потомком с помощью файла.

Вообще-то с помощью двух пайпов ;)

>А мне не надо установить двухстороннюю связь с программой /usr/bin/perl, т.е. эта
>сторонняя программа - она же не мой потомок. Как такое сделать?
>Как подключить эти самые пайпы не к своему потомку, а к
>вызываемой мною сторонней проге???

Я передаю данные (сторонней) программе sort, она сортирует эти данные, я получаю от нее отсортированные данные и печатаю их. Если это не то что вам нужно то объясните подробнее в чем отличие.


"Вызов внешней программы "
Отправлено Flex25 , 12-Май-06 00:14 
>Я передаю данные (сторонней) программе sort, она сортирует эти данные, я получаю
>от нее отсортированные данные и печатаю их. Если это не то
>что вам нужно то объясните подробнее в чем отличие.

На основе твоей программы я сделал следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  int p1[2], p2[2];
  FILE *f1, *f2;
  int i;
  char line[80];
  pipe(p1);
  pipe(p2);
  f1 = fdopen(p1[1], "w");
  f2 = fdopen(p2[0], "r");
  if (fork() == 0) {
    dup2(p1[0], 0); // stdin
    dup2(p2[1], 1); // stdout
    close(p1[1]);
    close(p2[0]);
    execlp("sort", "/usr/local/bin/perl", NULL);
  } else {
    close(p1[0]);
    close(p2[1]);
  }


  // Я передаю интерпретатору Perl код: print 'Hello World!!!';
  fprintf(f1, "print 'Hello World!!!!';");
  fclose(f1);

  // Я читаю результат
  while (fgets(line, sizeof(line), f2) != NULL) {
    printf("Итог выполнения Perl-программы: %s\n", line);
  }
  return 0;
}


В результате я получаю на выходе НЕ "Hello World!!!", "print 'Hello World';", т.е. моя программа не была исполнена.

ЧТО надо сделать, чтобу передать интерпретатору Perl программный код, а потом через пайпы получить результат в свою программу на stdin?


"Вызов внешней программы "
Отправлено gyn61 , 12-Май-06 00:21 
Вместо
  execlp("sort", "/usr/local/bin/perl", NULL);
надо
  execlp("/usr/local/bin/perl", "/usr/local/bin/perl", NULL);

"Вызов внешней программы "
Отправлено Flex25 , 12-Май-06 00:32 
>Вместо
>  execlp("sort", "/usr/local/bin/perl", NULL);
>надо
>  execlp("/usr/local/bin/perl", "/usr/local/bin/perl", NULL);

Ой, это я ступил!!!!

СПАСИБО ОГРОМНОЕ, все заработало!!! Ты даже не представляешь, как меня выручил!!!