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

Da Gambas-it.org - Wikipedia.
Riga 1: Riga 1:
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>
+
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=
 
=Programma C che invia "immediatamente" e "una volta" soltanto dati all'output non appena avviato=
Riga 10: Riga 9:
 
===Esempio pratico===
 
===Esempio pratico===
 
Facciamo, dunque, un semplice esempio, nel quale il codice dell'applicativo Gambas include anche il codice del programma scritto in C:
 
Facciamo, dunque, un semplice esempio, nel quale il codice dell'applicativo Gambas include anche il codice del programma scritto in C:
  '''Public''' Sub Main()
+
  Public Sub Main()
 
   
 
   
 
   Dim s As String
 
   Dim s As String
Riga 22: Riga 21:
 
   Print "Il PID dell'applicativo Gambas letto dalla variabile 's' = "; <FONT color=#B22222>s</font>
 
   Print "Il PID dell'applicativo Gambas letto dalla variabile 's' = "; <FONT color=#B22222>s</font>
 
   
 
   
  '''End'''
+
  End
 
   
 
   
  '''Private''' Procedure Crea_C()
+
   
 +
Private Procedure Crea_C()
 
   
 
   
 
   File.Save("/tmp/programma_C.c", "#include <stdio.h>\n\n" &
 
   File.Save("/tmp/programma_C.c", "#include <stdio.h>\n\n" &
Riga 32: Riga 32:
 
   Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 
   Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 
   
 
   
  '''End'''
+
  End
 
====Altro esempio====
 
====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''.
 
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''.
Riga 39: Riga 39:
 
   
 
   
 
   
 
   
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
   
 
   
 
  <FONT color=gray>' ''Va a creare il programma scritto in C:''</font>
 
  <FONT color=gray>' ''Va a creare il programma scritto in C:''</font>
 
   Crea_C()
 
   Crea_C()
 
   
 
   
  '''End'''
+
  End
 +
 
   
 
   
  '''Public''' Sub Button1_Click()
+
  Public Sub Button1_Click()
 
   
 
   
 
   Dim s As String
 
   Dim s As String
Riga 57: Riga 58:
 
   Inc i
 
   Inc i
 
   
 
   
  '''End'''
+
  End
 +
 
   
 
   
  '''Private''' Procedure Crea_C()
+
  Private Procedure Crea_C()
 
   
 
   
 
   File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
 
   File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
Riga 72: Riga 74:
 
   Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 
   Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 
   
 
   
  '''End'''
+
  End
  
 
=Programma C che invia dati allo ''standard output'' durante il suo funzionamento=
 
=Programma C che invia dati allo ''standard output'' durante il suo funzionamento=
Riga 85: Riga 87:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
   
 
   
 
  <FONT color=gray>' ''Va a creare il programma scritto in C:''</font>
 
  <FONT color=gray>' ''Va a creare il programma scritto in C:''</font>
Riga 92: Riga 94:
 
   <FONT color=blue>pr</font> = Shell "/tmp/programma_C" <FONT color=#B22222>For Input As "Processo"</font>
 
   <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 103: Riga 106:
 
   Print "Dato intercettato: "; s
 
   Print "Dato intercettato: "; s
 
    
 
    
  '''End'''
+
  End
+
 
  '''Private''' Procedure Crea_C()
+
 
 +
  Private Procedure Crea_C()
 
   
 
   
 
   File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
 
   File.Save("/tmp/programma_C.c", "#include <stdio.h>\n" &
Riga 118: Riga 122:
 
   Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 
   Shell "gcc -o /tmp/programma_C /tmp/programma_C.c" Wait
 
   
 
   
  '''End'''
+
  End
 
====Altro esempio====
 
====Altro esempio====
 
  Private pr As Process
 
  Private pr As Process
 
   
 
   
 
   
 
   
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
+
 
   Crea()
 
   Crea()
 
+
 
   pr = Shell "/tmp/prova" For Input As "prova"
 
   pr = Shell "/tmp/prova" For Input As "prova"
 
 
'''End'''
 
 
   
 
   
 +
End
 +
 +
 +
Public Sub prova_Read()
 
   
 
   
'''Public''' Sub prova_Read()
 
 
 
 
   TextArea1.Text &= pr.ReadLine() & gb.NewLine
 
   TextArea1.Text &= pr.ReadLine() & gb.NewLine
 
 
'''End'''
 
 
   
 
   
 +
End
 +
 +
 +
Private Procedure Crea()
 
   
 
   
'''Private''' Procedure Crea()
 
 
 
 
   File.Save("/tmp/prova.c", "#include <stdio.h>\n" &
 
   File.Save("/tmp/prova.c", "#include <stdio.h>\n" &
 
   "#include <unistd.h>\n\n" &
 
   "#include <unistd.h>\n\n" &
Riga 151: Riga 155:
 
    
 
    
 
   Shell "gcc -o /tmp/prova /tmp/prova.c" Wait
 
   Shell "gcc -o /tmp/prova /tmp/prova.c" Wait
 
+
  '''End'''
+
  End
  
  
Riga 161: Riga 165:
 
<BR> - "''standard output'' ";
 
<BR> - "''standard output'' ";
 
<BR> - "''standard error'' ".
 
<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'' ". I ''descrittori'' di questi tre file sono rappresentati con i numeri: 0, 1 e 2.
+
<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 delle 08:57, 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.