Sto provando a scrivere una funzione C tramite Inline :: C che creerà e restituirà un riferimento di matrice a Perl ... di seguito è riportato il mio script e l'output. Sto allocando la matrice e la popola correttamente? In particolare, creo un array temporaneo di SV*
e li passo a av_make
e restituisco un riferimento creato con newRV_noinc
. I conteggi di riferimento sembrano buoni quando guardo il ref dell'array restituito con Devel :: Peek :: Dump, che sembra identico alla stessa struttura dati creata in perl direttamente.Come dovrei creare e restituire un arrayref in Inline :: C?
Non ho ancora capito cosa sia la mortalizzazione/sv_2mortal
o se ne ho bisogno qui. Apparentemente, Inline :: C chiama automaticamente sv_2mortal
sulle funzioni che restituiscono SV*
, che possono essere rilevanti o meno.
#!/usr/bin/env perl
use strict;
use warnings FATAL => "all";
use 5.010_000;
use Data::Dumper;
use autodie;
use Inline ('C');
use Devel::Peek;
my $from_perl = [0 .. 9];
my $from_c = inline_array_maker(10); #same as above but in C
say Dumper $from_perl;
Dump($from_perl);
say Dumper $from_c;
Dump($from_c);
__END__
__C__
SV* (int len){
int i;
SV ** tmp_buffer;
AV * arr;
tmp_buffer = malloc(sizeof(SV*) * len);
printf("allocating tmp_buffer of size %d\n", len);
for (i = 0; i < len; i++) {
tmp_buffer[i] = newSViv(i);
}
// is av_make the most efficient way of doing this?
printf("av_make\n");
arr = av_make(len, tmp_buffer);
printf("freeing tmp_buffer\n");
for (i = 0; i < len; i++) {
sv_free(tmp_buffer[i]);
}
free(tmp_buffer);
return newRV_noinc(arr);
}
Ottengo il seguente output.
allocating tmp_buffer of size 10
av_make
freeing tmp_buffer
$VAR1 = [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
];
SV = IV(0x20c7520) at 0x20c7530
REFCNT = 1
FLAGS = (PADMY,ROK)
RV = 0x21c0fa8
SV = PVAV(0x25c7ec8) at 0x21c0fa8
REFCNT = 1
FLAGS =()
ARRAY = 0x25a0e80
FILL = 9
MAX = 9
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = IV(0x20b2dd8) at 0x20b2de8
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 0
Elt No. 1
SV = IV(0x20b2fb8) at 0x20b2fc8
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 1
Elt No. 2
SV = IV(0x20c69f8) at 0x20c6a08
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 2
Elt No. 3
SV = IV(0x20c6a10) at 0x20c6a20
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 3
$VAR1 = [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
];
SV = IV(0x20d25c8) at 0x20d25d8
REFCNT = 1
FLAGS = (PADMY,ROK)
RV = 0x25ac6b8
SV = PVAV(0x25c7ea0) at 0x25ac6b8
REFCNT = 1
FLAGS =()
ARRAY = 0x25b9140
FILL = 9
MAX = 9
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = IV(0x25aca80) at 0x25aca90
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 0
Elt No. 1
SV = IV(0x25ac750) at 0x25ac760
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 1
Elt No. 2
SV = IV(0x25ac5e8) at 0x25ac5f8
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 2
Elt No. 3
SV = IV(0x25ac930) at 0x25ac940
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 3
non sapevo di 'MUTABLE_SV', perché è preferibile? Dovrebbe essere aggiornato [this] (http://perldoc.perl.org/perlguts.html#Reference-Counts-and-Mortality) per non suggerire typecasting? –
Si assicura che non si scriva 'const'. Presenterò una patch. – ikegami
Si potrebbe voler applicare anche la perlapi, non è nemmeno documentata lì e senza di essa sarei riluttante ad usarla. In effetti, la vedo solo documentata nelle perldeltas, che non utilizzerei come riferimento API per non perdere la nota "rimossa" in un delta successivo. –