Differenze tra le versioni di "Intercettare i dati inviati allo standard output da un programma C"

Da Gambas-it.org - Wikipedia.
 
(8 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Mostreremo due casi, nei quali un applicativo Gambas lancia mediante la funzione ''Shell'' un programma scritto in linguaggio C, e ne intercetta i dati che quest'ultimo invia allo "standard output" (<I>stdout</i>). <SUP>&#091;[[#Note|Nota 1]]&#093;</sup>
+
Mostreremo due casi, nei quali un applicativo Gambas lancia mediante l'istruzione "Shell" (o "Exec") un programma scritto in linguaggio C, e ne intercetta i dati che quest'ultimo invia allo "standard output" (<I>stdout</i>). <SUP>&#091;[[#Note|nota 1]]&#093;</sup>
  
 +
=Programma C che invia "immediatamente" e "una volta" soltanto dati all'output non appena avviato=
 +
In questo caso il programma Gambas avvia mediante "Shell" o "Exec" il programma scritto in C, il quale invia <SPAN Style="text-decoration:underline">immediatamente e una volta soltanto</span> i dati allo ''standard output''.
  
==Programma C che invia immediatamente dati all'output non appena avviato==
+
Il programma scritto in Gambas in tale circostanza intercetterà i dati, trasmessi dal programma in C allo ''standard output'', mediante la parola "'''To'''" assegnandoli ad una variabile stringa:
In questo caso il programma Gambas avvia il programma scritto in C, il quale invia immediatamente i dati
+
Shell "<FONT color=darkgreen>''/percorso/del/programma_C''</font>" <FONT color=#B22222>To variabile_stringa</font>
allo ''standard output''.
 
  
Il programma scritto in Gambas in tale circostanza intercetterà i dati, trasmessi dal programma in C allo ''standard output'', mediante la parola "To" assegnandoli ad una variabile stringa:
+
===Esempio pratico===
Shell "<FONT color=gray>''/percorso/del/programma_C''</font>" <FONT color=#B22222>To variabile_stringa</font>
+
Facciamo, dunque, un semplice esempio, nel quale il codice dell'applicativo Gambas include anche il codice del programma scritto in C:
 
+
Public Sub Main()
====Esempio pratico====
+
Facciamo, dunque, un semplice esempio.
+
  Dim s As String
 
+
Il codice del programma, scritto in C, sarà il seguente:
+
<FONT color=gray>' ''Va a creare il programma scritto in C:''</font>
#include <stdio.h>  
+
  Crea_C()
 +
 
 +
<FONT color=gray>' ''Avvia il programma, scritto in C, inviandogli - come argomento - il PID del programma Gambas:''</font>
 +
  Shell "/tmp/programma_C " & Application.Handle <FONT color=#B22222>To s</font>
 +
 +
  Print "Il PID dell'applicativo Gambas letto dalla variabile 's' = "; <FONT color=#B22222>s</font>
 +
 +
End
 +
 +
 +
Private Procedure Crea_C()
 +
 +
  File.Save("/tmp/programma_C.c", "#include <stdio.h>\n\n" &
 +
                                  "void main(int argc, char **argv) {  <FONT color=gray>/* Riceve il PID del programma Gambas */</font>\n" &
 +
                                  "  printf(\"%s\", argv[1]);\n}")
 +
 +
  Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 +
 +
End
 +
====Altro esempio====
 +
In quest'altro esempio sarà lanciato un programma in C, al quale si passerà un valore di tipo ''Stringa''. Il programma, quindi, convertirà in un numerico ''Intero'' questo valore ricevuto e, dopo averlo sommato al valore 100, lo scriverà nello ''standard output''. Il programma Gambas intercetterà il dato dallo ''standard output'' e lo mostrerà, come nel caso precedente, in una ''TextArea''.
 +
Private pr As Process
 +
Private i As Integer
 +
 +
 +
Public Sub Form_Open()
 +
 +
<FONT color=gray>' ''Va a creare il programma scritto in C:''</font>
 +
  Crea_C()
 
   
 
   
 +
End
 
   
 
   
void main(int argc, char **argv) {          <FONT color=gray>/* Riceve il PID del programma Gambas */</font>
 
 
   
 
   
  printf("%s", argv[1]);
+
  Public Sub Button1_Click()
 
 
  }
 
 
 
 
 
Il codice dell'applicativo Gambas sarà il seguente:
 
'''Public''' Sub Main()
 
 
   
 
   
 
   Dim s As String
 
   Dim s As String
 
 
<FONT color=gray>' ''Avvia il programma, scritto in C, inviadogli - come argomento - il PID del programma Gambas:''</font>
 
  Shell "<FONT color=gray>''/percorso/del/programma_C''</font> " & Application.Handle <FONT color=#B22222>To s</font>
 
 
   
 
   
   Print "Il PID dell'applicativo Gambas letto dalla variabile 's' = "; <FONT color=#B22222>s</font>
+
   Shell "/tmp/programma_C " & CStr(i) <FONT color=#B22222>To</font> s
 +
 +
  TextArea1.Text = s
 
   
 
   
  '''End'''
+
  <FONT Color=gray>' ''Ogni qual volta si clicca sul tasto, si vedrà nella ''TextArea'' il valore numerico incrementato di un'unità:''</font>
 
+
  Inc i
 
 
 
 
==Programma C che invia dati allo ''standard output'' durante il suo funzionamento==
 
In quest'altro caso il programma Gambas avvia il programma scritto in C, il quale invierà i dati allo ''standard output'' successivamente durante il suo funzionamento.
 
 
 
 
 
===Usando la Classe ''Process''===
 
Il programma scritto in Gambas in tale circostanza intercetterà i dati, trasmessi dal programma in C allo ''standard output'', ponendo in osservazione il processo aperto del programma C mediante le parole "''For Input''" (è necessaria la risorsa "''Input''" anziché "''Read''", perché è stato posta la funzione di attesa "''sleep( )''" nel codice del programma C).
 
<BR>Lo ''standard output'' del programma C sarà, quindi, intercettato da un'apposita subroutine di Gambas, che viene sollevata quando c'è qualcosa da leggere nello ''standard output''. I dati saranno raccolti da una specifica variabile appositamente dichiarata per gestire il processo avviato del programma scritto in C.
 
 
 
Facciamo, dunque, un semplice esempio.
 
 
 
Il codice del programma, scritto in C, sarà il seguente:
 
#include <stdio.h>
 
#include <unistd.h>
 
 
   
 
   
 +
End
 
   
 
   
void main() {
 
 
   
 
   
  int i;
+
Private Procedure Crea_C()
 
 
  for (i = 1; i <= 5000; i++) {
 
 
   
 
   
    if ((i % 100) == 0) {
+
  File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
      printf("%d\n", i);
+
                                  "#include <stdlib.h>\n\n" &
      sleep(1);
+
                                  "void main(int argc, char *argv[]) {\n\n" &
    }
+
                                  "  int a, b;\n\n" &
 +
                                  " <FONT color=blue>// Converte la Stringa in un numero \"Intero\":</font>\n" &
 +
                                  "  a = atoi(argv[ 1 ]);\n" &
 +
                                  "  b = a + 100;\n" &
 +
                                  "  printf(\"%d\", b);\n}")
 
   
 
   
   }
+
   Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 
   
 
   
  }
+
  End
  
 +
=Programma C che invia dati allo ''standard output'' durante il suo funzionamento=
 +
In quest'altro caso il programma Gambas avvia il programma scritto in C, il quale invierà i dati allo ''standard output'' successivamente, dopo uno o anche più intervalli di tempo, durante il suo funzionamento.
  
Il codice dell'applicativo Gambas sarà il seguente:
+
==Usando la Classe ''Process''==
 +
Il programma scritto in Gambas in tale circostanza intercetterà i dati, trasmessi dal programma in C allo ''standard output'', ponendo in osservazione il processo aperto del programma C mediante le parole "''For Input''" (è necessaria la risorsa "''Input'' " anziché "''Read'' ", perché è stato posta la funzione di attesa "''sleep( )'' " nel codice del programma C).
 +
<BR>Lo ''standard output'' del programma C sarà, quindi, intercettato da un'apposita subroutine di Gambas, che viene sollevata quando c'è qualcosa da leggere nello ''standard output''. I dati saranno raccolti da una specifica variabile appositamente dichiarata per gestire il processo avviato del programma scritto in C.
 +
 
 +
Facciamo, dunque, un semplice esempio, nel quale il codice dell'applicativo Gambas, contenente anche il codice del programma scritto in C, sarà il seguente:
 
  Private <FONT color=blue>pr</font> As Process
 
  Private <FONT color=blue>pr</font> As Process
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
   
 
   
   <FONT color=blue>pr</font> = Shell "<FONT color=gray>''/percorso/del/programma_C''</font>" <FONT color=#B22222>For Input As "processo"</font>
+
<FONT color=gray>' ''Va a creare il programma scritto in C:''</font>
 +
  Crea_C()
 +
 +
   <FONT color=blue>pr</font> = Shell "/tmp/programma_C" <FONT color=#B22222>For Input As "Processo"</font>
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub <FONT color=#B22222>processo_Read()</font>
+
  Public Sub <FONT color=#B22222>processo_Read()</font>
 
    
 
    
 
   Dim s As String
 
   Dim s As String
Riga 88: Riga 106:
 
   Print "Dato intercettato: "; s
 
   Print "Dato intercettato: "; s
 
    
 
    
  '''End'''
+
  End
  
 
+
 
===Usando la Classe ''File''===
+
Private Procedure Crea_C()
la seguente modalità è simile alla precedente, ma si porrà in osservazione con la parola-chiave "''Watch''" il file-device "''/dev/stdout''" aperto con la funzione "''Open''".
+
 
+
  File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
Mostriamo un esempio.
+
                                  "#include <unistd.h>\n\n" &
 
+
                                  "void main() {\n\n" &
Il codice del programma, scritto in C, sarà ancora una volta il seguente:
+
                                  "  int i;\n\n" &
#include <stdio.h>
+
                                  "  for (i = 1; i <= 5000; i++) {\n" &
#include <unistd.h>
+
                                  "    if ((i % 100) == 0) {\n" &
 +
                                  "      printf(\"%d\\n\", i);\n" &
 +
                                  "      sleep(1);\n    }\n  }\n}")
 +
 +
  Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 +
 +
End
 +
====Altro esempio====
 +
Private pr As Process
 +
 
   
 
   
 +
Public Sub Form_Open()
 
   
 
   
void main() {
+
  Crea()
 
   
 
   
   int i;
+
   pr = Shell "/tmp/prova" For Input As "prova"
 
 
  for (i = 1; i <= 5000; i++) {
 
 
   
 
   
    if ((i % 100) == 0) {
+
End
      printf("%d\n", i);
 
      sleep(1);
 
    }
 
 
   
 
   
  }
 
 
   
 
   
  }
+
  Public Sub prova_Read()
 
 
 
 
Il codice dell'applicativo Gambas sarà il seguente:
 
Private fl As File
 
 
   
 
   
 +
  TextArea1.Text &= pr.ReadLine() & gb.NewLine
 
   
 
   
  '''Public''' Sub Main()
+
  End
 
   
 
   
  Shell "<FONT color=gray>''/percorso/del/programma_C''</font>"
 
 
 
  fl = Open "/dev/stdout" For Read <FONT color=#B22222>Watch</font>
 
 
 
'''End'''
 
 
   
 
   
 +
Private Procedure Crea()
 
   
 
   
'''Public''' Sub File_Read()
+
  File.Save("/tmp/prova.c", "#include <stdio.h>\n" &
 +
  "#include <unistd.h>\n\n" &
 +
  "int a;\n\n" &
 +
  "void main() {\n\n" &
 +
  "  while (1) {\n" &
 +
  "    printf(\"%d\\n\", a);\n" &
 +
  "    sleep(1);\n" &
 +
  "    a++;\n}\n\n}")
 
    
 
    
   Dim s As String
+
   Shell "gcc -o /tmp/prova /tmp/prova.c" Wait
 
   
 
   
  <FONT color=gray>' ''Legge i dati dalla variabile di tipo "File", con la quale si gestisce il file-device "/dev/stdout":''</font>
+
  End
  Line Input #fl, s
+
 
 
 
  Print "Dato intercettato: "; s
 
 
 
'''End'''
 
  
  
 
=Note=
 
=Note=
[1] Quando un programma viene eseguito, il sistema operativo genera tre file chiamati rispettivamente: "''standard input''", "''standard output''" e "''standard error''".  
+
[1] Quando un programma viene eseguito, il sistema operativo genera tre file chiamati rispettivamente:
<BR>Di norma lo "''standard input''" è riferito alla tastiera, mentre lo "''standard output''" e lo "''standard error''" sono riferiti allo schermo. Ogni rapporto e riferimento ai file avviene attraverso un proprio Puntatore al file, chiamato "''descrittore di file''". I ''descrittori'' di questi tre file sono rappresentati con i numeri: 0, 1 e 2.
+
<BR> - "''standard input'' ";
 +
<BR> - "''standard output'' ";
 +
<BR> - "''standard error'' ".
 +
<BR>Di norma lo ''Standard Input'' è riferito alla tastiera, mentre lo ''Standard Output'' e lo ''Standard Error'' sono riferiti allo schermo.
 +
<BR>Ogni rapporto e riferimento ai file avviene attraverso un proprio Puntatore al file, chiamato "''descrittore di file'' ".  
 +
<BR>I ''descrittori'' di questi tre file sono rappresentati con i numeri: 0, 1 e 2.
 
<BR>0 = "''standard input'' ": il programma legge i dati scritti/inviati dalla periferica.
 
<BR>0 = "''standard input'' ": il programma legge i dati scritti/inviati dalla periferica.
 
<BR>1 = "''standard output'' ": il programma scrive/invia dati alla periferica, la quale legge i dati inviati dal programma.
 
<BR>1 = "''standard output'' ": il programma scrive/invia dati alla periferica, la quale legge i dati inviati dal programma.
 
<BR>2 = "''standard error'' ": il programma scrive/invia messaggi d'errore al video.
 
<BR>2 = "''standard error'' ": il programma scrive/invia messaggi d'errore al video.
 +
<BR>I dati introdotti in input con la tastiera vengono inseriti all'interno di un canale costituito da una sequenza continua di byte. Allo stesso modo i dati prodotti a video vengono inseriti all'interno di un altro canale. Tali canali vengono definiti ''standard input'' e ''standard output''. Pertanto la tastiera e' il canale ''standard input'' ed il video e' il canale ''standard output''. Qualsiasi comando quindi, accetta in input dei valori che legge dallo ''standard input'' (la tastiera) e produce dei risultati scrivendoli nello ''standard output'' (il video). Ma un comando può produrre anche dei messaggi di errore se per esempio vengono introdotti dei valori in input non validi. I messaggi di errore dei comandi vengono scritti in un terzo canale, lo ''standard error''.
 +
<BR>Come già visto, ogni canale standard e' identificabile da un numero: 0 per il canale ''standard input'', 1 per il canale ''standard output'' e 2 per il canale ''standard error''.

Versione attuale delle 09:01, 7 gen 2024

Mostreremo due casi, nei quali un applicativo Gambas lancia mediante l'istruzione "Shell" (o "Exec") un programma scritto in linguaggio C, e ne intercetta i dati che quest'ultimo invia allo "standard output" (stdout). [nota 1]

Programma C che invia "immediatamente" e "una volta" soltanto dati all'output non appena avviato

In questo caso il programma Gambas avvia mediante "Shell" o "Exec" il programma scritto in C, il quale invia immediatamente e una volta soltanto i dati allo standard output.

Il programma scritto in Gambas in tale circostanza intercetterà i dati, trasmessi dal programma in C allo standard output, mediante la parola "To" assegnandoli ad una variabile stringa:

Shell "/percorso/del/programma_C" To variabile_stringa

Esempio pratico

Facciamo, dunque, un semplice esempio, nel quale il codice dell'applicativo Gambas include anche il codice del programma scritto in C:

Public Sub Main()

 Dim s As String

' Va a creare il programma scritto in C:
 Crea_C()
 
' Avvia il programma, scritto in C, inviandogli - come argomento - il PID del programma Gambas:
 Shell "/tmp/programma_C " & Application.Handle To s

 Print "Il PID dell'applicativo Gambas letto dalla variabile 's' = "; s

End


Private Procedure Crea_C()

 File.Save("/tmp/programma_C.c", "#include <stdio.h>\n\n" &
                                 "void main(int argc, char **argv) {   /* Riceve il PID del programma Gambas */\n" &
                                 "   printf(\"%s\", argv[1]);\n}")

 Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait

End

Altro esempio

In quest'altro esempio sarà lanciato un programma in C, al quale si passerà un valore di tipo Stringa. Il programma, quindi, convertirà in un numerico Intero questo valore ricevuto e, dopo averlo sommato al valore 100, lo scriverà nello standard output. Il programma Gambas intercetterà il dato dallo standard output e lo mostrerà, come nel caso precedente, in una TextArea.

Private pr As Process
Private i As Integer


Public Sub Form_Open()

' Va a creare il programma scritto in C:
 Crea_C()

End


Public Sub Button1_Click()

 Dim s As String

 Shell "/tmp/programma_C " & CStr(i) To s

 TextArea1.Text = s

' Ogni qual volta si clicca sul tasto, si vedrà nella TextArea il valore numerico incrementato di un'unità:
 Inc i

End


Private Procedure Crea_C()

 File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
                                 "#include <stdlib.h>\n\n" &
                                 "void main(int argc, char *argv[]) {\n\n" &
                                 "   int a, b;\n\n" &
                                 " // Converte la Stringa in un numero \"Intero\":\n" &
                                 "   a = atoi(argv[ 1 ]);\n" &
                                 "   b = a + 100;\n" &
                                 "   printf(\"%d\", b);\n}")

 Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait

End

Programma C che invia dati allo standard output durante il suo funzionamento

In quest'altro caso il programma Gambas avvia il programma scritto in C, il quale invierà i dati allo standard output successivamente, dopo uno o anche più intervalli di tempo, durante il suo funzionamento.

Usando la Classe Process

Il programma scritto in Gambas in tale circostanza intercetterà i dati, trasmessi dal programma in C allo standard output, ponendo in osservazione il processo aperto del programma C mediante le parole "For Input" (è necessaria la risorsa "Input " anziché "Read ", perché è stato posta la funzione di attesa "sleep( ) " nel codice del programma C).
Lo standard output del programma C sarà, quindi, intercettato da un'apposita subroutine di Gambas, che viene sollevata quando c'è qualcosa da leggere nello standard output. I dati saranno raccolti da una specifica variabile appositamente dichiarata per gestire il processo avviato del programma scritto in C.

Facciamo, dunque, un semplice esempio, nel quale il codice dell'applicativo Gambas, contenente anche il codice del programma scritto in C, sarà il seguente:

Private pr As Process


Public Sub Main()

' Va a creare il programma scritto in C:
 Crea_C()

 pr = Shell "/tmp/programma_C" For Input As "Processo"
 
End


Public Sub processo_Read()
 
 Dim s As String

' Legge i dati dalla variabile, con la quale si gestisce il processo:
 Line Input #pr, s
 
 Print "Dato intercettato: "; s
  
End


Private Procedure Crea_C()

 File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
                                 "#include <unistd.h>\n\n" &
                                 "void main() {\n\n" &
                                 "   int i;\n\n" &
                                 "   for (i = 1; i <= 5000; i++) {\n" &
                                 "     if ((i % 100) == 0) {\n" &
                                 "       printf(\"%d\\n\", i);\n" &
                                 "       sleep(1);\n     }\n   }\n}")

 Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait

End

Altro esempio

Private pr As Process


Public Sub Form_Open()

 Crea()

 pr = Shell "/tmp/prova" For Input As "prova"

End


Public Sub prova_Read()

 TextArea1.Text &= pr.ReadLine() & gb.NewLine

End


Private Procedure Crea()

 File.Save("/tmp/prova.c", "#include <stdio.h>\n" &
 "#include <unistd.h>\n\n" &
 "int a;\n\n" &
 "void main() {\n\n" &
 "   while (1) {\n" &
 "     printf(\"%d\\n\", a);\n" &
 "     sleep(1);\n" &
 "     a++;\n}\n\n}")
 
 Shell "gcc -o /tmp/prova /tmp/prova.c" Wait

End


Note

[1] Quando un programma viene eseguito, il sistema operativo genera tre file chiamati rispettivamente:
- "standard input ";
- "standard output ";
- "standard error ".
Di norma lo Standard Input è riferito alla tastiera, mentre lo Standard Output e lo Standard Error sono riferiti allo schermo.
Ogni rapporto e riferimento ai file avviene attraverso un proprio Puntatore al file, chiamato "descrittore di file ".
I descrittori di questi tre file sono rappresentati con i numeri: 0, 1 e 2.
0 = "standard input ": il programma legge i dati scritti/inviati dalla periferica.
1 = "standard output ": il programma scrive/invia dati alla periferica, la quale legge i dati inviati dal programma.
2 = "standard error ": il programma scrive/invia messaggi d'errore al video.
I dati introdotti in input con la tastiera vengono inseriti all'interno di un canale costituito da una sequenza continua di byte. Allo stesso modo i dati prodotti a video vengono inseriti all'interno di un altro canale. Tali canali vengono definiti standard input e standard output. Pertanto la tastiera e' il canale standard input ed il video e' il canale standard output. Qualsiasi comando quindi, accetta in input dei valori che legge dallo standard input (la tastiera) e produce dei risultati scrivendoli nello standard output (il video). Ma un comando può produrre anche dei messaggi di errore se per esempio vengono introdotti dei valori in input non validi. I messaggi di errore dei comandi vengono scritti in un terzo canale, lo standard error.
Come già visto, ogni canale standard e' identificabile da un numero: 0 per il canale standard input, 1 per il canale standard output e 2 per il canale standard error.