Good afternoon, you need to run a python script that sends data as a print to the console and read this data in a C program.

Sort of:

char buf[256]; start ("python foo.py", &buf); 

Where buf is the entire output of the script.

  • In off. documentation, like, there are examples of this. Watched? Or did not help? - LEQADA
  • You did not understand, you need to start the application from the C program and get its output, this is not necessarily a Python script, it may be a .bat file or a console application - Indev

3 answers 3

For Linux

 #include <stdio.h> int main() { FILE * uname; char os[80]; int lastchar; uname = popen("uname -o", "r"); lastchar = fread(os, 1, 80, uname); os[lastchar] = '\0'; printf("Your OS is %s", os); pclose(uname); return 0; } 

Link to the original

PS uname -o displays the name of the OS in Linux.

For windows

For Windows, there is an analogue popen :

 FILE *_popen(const char *command,const char *mode); 

Options:

command is an executable command, mode is the state of the returned expression.

Values mode :

"r" - The calling process can read the standard output of the spawned command using the returned stream.

"w" - The calling process can write to the standard input of the child command using the return stream.

"b" - Open in binary mode.

"t" - Open in text mode.

Link to off. documentation

 #include <stdio.h> #include <stdlib.h> int main( void ) { char psBuffer[128]; FILE *pPipe; if( (pPipe = _popen( "dir *.c /on /p", "rt" )) == NULL ) exit( 1 ); /* Read pipe until end of file, or an error occurs. */ while(fgets(psBuffer, 128, pPipe)) { printf(psBuffer); } /* Close pipe and print return value of pPipe. */ if (feof( pPipe)) { printf( "\nProcess returned %d\n", _pclose( pPipe ) ); } else { printf( "Error: Failed to read the pipe to the end.\n"); } } 

Unfortunately, there is no way to check the code.

  • Well, what to do in Windows? - Indev
  • @Indev, updated the answer - LEQADA
  • Thanks, what you need - Indev

In Unix, your problem can be solved as follows:

  1. Create an unnamed pipe (call Pipe () );
  2. spawn a child process ( fork () call);
  3. if you want to transfer data only from the child process (we run your script there) to the parent (your program in C), then in the parent process we leave only the channel descriptor open for reading, close for writing, in the child process - on the contrary, close the channel descriptor for reading , leave a handle to the record;
  4. if we want all messages (including errors) from the program running in the child process to be dumped into the parent process, we redirect all output streams of the child process to the channel descriptor for recording by calling dup2 () ;
  5. One of the calls to the exec () family (there are a lot of them, see which one is more convenient for you to use) run the program / utility / script you need in the child process, do not forget to check that the exec () was executed without errors, we don’t do anything else in the child process code .
  6. in the parent process, from the unclosed channel descriptor that remains unclosed, we read what the script launched in the child process displays.

* All the nuances regarding the use of system calls can be searched in mana, or, for example, look in the books of Stevens.

    I'll add 5 more kopecks to the Linux solutions.

    Use forkpty to get the link to the command being run. The essential difference from the previous options is that we get a bidirectional "terminal-like" ( pty ) connection. In principle, this way (well, by adding something to the pseudo-terminal control) you can simulate a real dialogue with any program (for example, vi (?)), Although it is most applicable for su / ssh, etc., refusing to read the password not from the terminal (but not only, because generally, the behavior of FILE * depends on whether it works with a terminal or a file, pipe, etc.).

    Of course, within the framework of this question, such opportunities are redundant, but still ...

     // compile gcc (or g++) with -lutil // Запустим переданные аргументы командной строки, как команду // и напечатаем ее stdout/stderr, // а затем выведем результат ее работы (код возврата) #include <stdio.h> #include <unistd.h> #include <pty.h> #include <err.h> #include <sysexits.h> #include <sys/wait.h> int main (int ac, char *av[]) { int tty; pid_t child = forkpty(&tty, 0, 0, 0); // в этой точке у нас работают (надеемся!) уже два процесса (один запущен внутри forkpty) // поэтому проявите особое внимание к вставке сюда какого-то кода switch (child) { case -1: err(EX_OSERR, "forkpty"); // never Returns case 0: // эта часть switch исполняется в "дочернем" процессе!!! // запустим команду, которая будет писать в наш tty execvp(av[1], &av[1]); // при успешном вызове возврата не будет err(EX_UNAVAILABLE, "execvp"); // never Returns } // а здесь уже наверняка опять один процесс (исходный "папа") char *str = 0; size_t ssz; FILE *in = fdopen(tty, "r"); // привяжем к tty FILE while (getline(&str, &ssz, in) != EOF) // getline() еще одна удобная GNU штучка fputs(str, stdout); fclose(in); // tty закроется здесь int s, rc; wait(&s); // мы запускали один процесс и ждем его завершения, так что можно не изгаляться с waitpid/wait3 и т.п. // корректная обработка всех возможных ситуаций немного длинее, для простоты опустим их const char *msg = WIFEXITED(s) ? "exited with code" : "terminated by signal"; rc = *msg == 'e' ? WEXITSTATUS(s) : WTERMSIG(s); printf("---- %s (%ld) %s %d ----\n", av[1], (long)child, msg, rc); return puts("End") == EOF; } 

    Now run and see:

     avp@avp-xub11:hashcode$ g++ -Wall tc -lutil ; ./a.out ls -alR /tmp /tmp: total 32 drwxrwxrwt 6 root root 4096 Nov 2 13:08 . drwxr-xr-x 24 root root 4096 Oct 20 15:07 .. -rw------- 1 avp avp 0 Oct 29 13:35 config-err-TwtmYo drwx------ 2 avp avp 4096 Oct 29 13:36 .esd-1000 drwx------ 2 lightdm lightdm 4096 Oct 29 13:36 .esd-104 drwxrwxrwt 2 root root 4096 Oct 29 13:35 .ICE-unix -r--r--r-- 1 root root 11 Oct 29 13:34 .X0-lock drwxrwxrwt 2 root root 4096 Oct 29 13:34 .X11-unix -rw------- 1 avp avp 418 Oct 29 13:35 .xfsm-ICE-NLCL7X /tmp/.esd-1000: total 8 drwx------ 2 avp avp 4096 Oct 29 13:36 . drwxrwxrwt 6 root root 4096 Nov 2 13:08 .. srwxrwxrwx 1 avp avp 0 Oct 29 13:36 socket ls: cannot open directory /tmp/.esd-104: Permission denied /tmp/.ICE-unix: total 8 drwxrwxrwt 2 root root 4096 Oct 29 13:35 . drwxrwxrwt 6 root root 4096 Nov 2 13:08 .. srwxrwxrwx 1 avp avp 0 Oct 29 13:35 2019 /tmp/.X11-unix: total 8 drwxrwxrwt 2 root root 4096 Oct 29 13:34 . drwxrwxrwt 6 root root 4096 Nov 2 13:08 .. srwxrwxrwx 1 root root 0 Oct 29 13:34 X0 ---- ls (14744) exited with code 2 ---- End avp@avp-xub11:hashcode$ avp@avp-xub11:hashcode$ ./a.out hjsdjhdj a.out: execvp: No such file or directory ---- hjsdjhdj (14783) exited with code 69 ---- End avp@avp-xub11:hashcode$