Disclaimer: l'autore della domanda ha una conoscenza media di Erlang e una conoscenza di base di C.C e Erlang: esempio Erlang Port
Sto leggendo il Interoperability Tutorial User Guide ora. Ho compilato con successo l'esempio complex.c
e funziona con la porta Erlang senza problemi.
Tuttavia, mi piacerebbe capire come funziona il codice C attuale. Lo capisco in generale: nell'esempio legge 2 byte dallo standard input e controlla il primo byte. A seconda del primo byte, chiama la funzione foo
o bar
. Questo è il limite della mia comprensione di questo momento.
Quindi, se prendiamo entrambi erl_comm.c
:
/* erl_comm.c */
typedef unsigned char byte;
read_cmd(byte *buf)
{
int len;
if (read_exact(buf, 2) != 2)
return(-1);
len = (buf[0] << 8) | buf[1];
return read_exact(buf, len);
}
write_cmd(byte *buf, int len)
{
byte li;
li = (len >> 8) & 0xff;
write_exact(&li, 1);
li = len & 0xff;
write_exact(&li, 1);
return write_exact(buf, len);
}
read_exact(byte *buf, int len)
{
int i, got=0;
do {
if ((i = read(0, buf+got, len-got)) <= 0)
return(i);
got += i;
} while (got<len);
return(len);
}
write_exact(byte *buf, int len)
{
int i, wrote = 0;
do {
if ((i = write(1, buf+wrote, len-wrote)) <= 0)
return (i);
wrote += i;
} while (wrote<len);
return (len);
}
e port.c
:
/* port.c */
typedef unsigned char byte;
int main() {
int fn, arg, res;
byte buf[100];
while (read_cmd(buf) > 0) {
fn = buf[0];
arg = buf[1];
if (fn == 1) {
res = foo(arg);
} else if (fn == 2) {
res = bar(arg);
}
buf[0] = res;
write_cmd(buf, 1);
}
}
Che cosa significa ogni funzione effettivamente fare lì? Che scopo servono effettivamente le variabili li, len, i, wrote, got
?
Alcune più piccole domande:
- Perché le funzioni non hanno alcun tipo di ritorno, anche
void
s? - Quando la porta di Erlang invia i dati a C, il primo byte determina una funzione da chiamare. Se il byte contiene il decimale 1, viene chiamato
foo()
, se il byte contiene il decimale 2, quindi viene chiamatobar()
. In caso contrario, è possibile utilizzare questo protocollo per richiamare fino a 255 funzioni C diverse con un solo parametro ciascuna. È giusto? - "L'aggiunta dell'indicatore di lunghezza verrà eseguita automaticamente dalla porta di Erlang, ma deve essere eseguita esplicitamente nel programma C esterno". Cosa significa? Su quale linea di codice è fatta?
- Dall'esercitazione: "Per impostazione predefinita, il programma C deve leggere dallo standard input (descrittore di file 0) e scrivere sullo standard output (descrittore di file 1)." Quindi: "Nota che stdin e stdout sono per input/output bufferizzati e non dovrebbero essere usati per la comunicazione con Erlang!" Qual è il trucco qui?
- perché
buf
viene inizializzato su[100]
?
La tua ipotesi su 'buf' è corretta. È un array, cioè un'area di memoria contigua in grado di contenere elementi 'n' di un tipo specificato. In questo scenario, la memoria viene allocata nello stack. Un modo diverso di allocare la memoria sarebbe quello di rendere 'buf' un puntatore e allocarlo nell'heap usando' malloc' (ma poi si deve essere sicuri di 'liberare' la memoria da soli quando si ha finito con esso). –
Riguardo a 4. Prima il tutorial dice che il programma C dovrebbe leggere da stdin (descrittore di file 0) e scrivere su stdout (descrittore di file 1). Quindi il tutorial dice che stdin/stdout non dovrebbe essere usato per la comunicazione con Erlang. "Non è una contraddizione diretta? Forniscono un esempio di programma C che usa stdin/stdout e poi dicono che non dovrebbe essere usato, perché stdin/stdout è memorizzato nel buffer.Perché mi manca qualcosa qui .. – skanatek
@MartinLee - Oh, è vero, suppongo, l'ho inteso nel senso che non dovresti usare queste porte per avere una comunicazione avanti e indietro tra i processi di Erlang e C (questo è ciò che la cosa C Node è per) .Non siamo però: Erlang sta inviando una singola richiesta e si aspetta una singola risposta 'int' per invocazione del programma.Probabilmente potrei aver frainteso o letto male – Inaimathi