Inline :: C è abbastanza intelligente per estrarre i valori da SV
in base alla firma del tipo di funzione C. Ma se vuoi passare strutture complesse in Perl a funzioni C, devi usare lo Perl API per estrarre i valori. Quindi, ecco cosa è necessario sapere per questo problema:
Una matrice è un'istanza di un C struct
chiamato AV
. Un riferimento è implementato da struct
chiamato RV
. Tutti questi sono "sottotipi" (kinda) di una base struct
denominata SV
.
Quindi per far funzionare questa funzione dobbiamo fare alcune cose.
- Modificare il tipo di parametro su
SV *
(puntatore su SV
).
- utilizzare l'API per verificare se questo particolare
SV
è un riferimento al contrario di qualche altro tipo di scalare
- Controllare il camper per assicurarsi che sta puntando a un array e non qualcos'altro.
- Dereference the
RV
per ottenere il SV
a cui punta.
- Poiché sappiamo che
SV
è una matrice, lanciarla su AV
e iniziare a lavorarci.
- Cerca il terzo elemento di tale array, che è un altro
SV
.
- Verificare che il
SV
abbiamo ottenuto dalla matrice è un valore numerico adatto per C printf
- Estrarre il numerico effettivo dal
SV
.
- Stampare il messaggio
Quindi mettere che tutti insieme, si ottiene qualcosa di simile:
use Inline C;
my @abc = (1.9, 2.3, 3.8);
foo(\@abc);
__END__
__C__
void foo(SV *abc)
{
AV *array; /* this will hold our actual array */
SV **value; /* this will hold the value we extract, note that it is a double pointer */
double num; /* the actual underlying number in the SV */
if (!SvROK(abc)) croak("param is not a reference");
if (SvTYPE(SvRV(abc)) != SVt_PVAV) croak("param is not an array reference");
/* if we got this far, then we have an array ref */
/* now dereference it to get the AV */
array = (AV *)SvRV(abc);
/* look up the 3rd element, which is yet another SV */
value = av_fetch(array, 2, 0);
if (value == NULL) croak("Failed array lookup");
if (!SvNOK(*value)) croak("Array element is not a number");
/* extract the actual number from the SV */
num = SvNV(*value);
printf("C = %f\n", num);
}
fa Kinda apprezzare quanto lavoro Perl fa sotto il cofano. :)
Ora, non devi essere tanto esplicito quanto quell'esempio. Puoi liberarti di alcune variabili temporanee facendo cose in linea, ad es.
printf("C = %f\n", SvNV(*value));
eliminerebbe la necessità di dichiarare num
. Ma ho voluto far capire quanto è necessario dereferenziazione e il tipo di controllo per attraversare una struttura Perl in C.
E come @mob sottolinea qui di seguito, in realtà non hanno a che fare tutto che lavorano (se è una buona idea di essere a conoscenza di come funziona.)
Inline :: C è abbastanza intelligente che se si dichiara la funzione come
void foo(AV *abc) {
...
}
sarà scartare automaticamente la AV
per voi e si può andare direttamente al passo av_fetch
.
Se tutto questo sembra sconcertante a voi, mi raccomando dare un'occhiata a:
- Il Perlguts Illustrated PDF, quindi
- Il
perlguts
pagina di manuale, e quindi
- Il Inline::C Cookbook, consultando
- La manpage
perlapi
.
Sono nuovo in Perl, ma la riga 7 è la linea su cui si definisce la matrice, si sta definendo la matrice correttamente. Stai passando in modo corretto (con il /?) Ha bisogno di essere convertito in un array C tramite qualcosa in A.P.I (Non come funziona XD)? –