How do I create and return arrayref in Inline :: C?

I am trying to write a C function through Inline :: C, which will create and return an array reference for Perl ... below is my script and output. Am I allocating an array and populating it correctly? In particular, I create a temporary SV* array and pass it to av_make and return the link created using newRV_noinc . The link metrics seem great when I look at the ref returned array with Devel :: Peek :: Dump, which looks identical to the same data structure created directly in perl.

I still do not understand what mortality / sv_2mortal , or if I need it here. Apparently, Inline :: C automatically calls sv_2mortal for functions that return SV* , which may or may not be relevant.

 #!/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); } 

I get the following 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 
+6
source share
2 answers

Have you read perldoc perlguts ? He should get most of the way from you. Inline::C can handle the return value of AV* . I could do something like:

 #!/usr/bin/env perl use strict; use warnings; use Inline C => <<'END'; AV* make_arrayref (int size) { int i; AV* ret = newAV(); sv_2mortal((SV*)ret); for(i=0; i<size; i++) { av_push(ret, newSViv(i) ); } return ret; } END my $arrayref = make_arrayref(10); print "$_\n" for @$arrayref; 

Here is the code I wrote that can help too.

+7
source

I still do not understand what mortality / sv _2mortal is, or if I need it here. Apparently, Inline :: C automatically calls sv_2mortal for functions that return SV *, which may or may not be relevant.

When you allocated RV, you became its owner. If you give up your deduction, you need to reduce its conversion rate. But this will free him in place, since no one else refers to him. Mortalising is a delayed recount. This gives the caller the opportunity to first capture him (and increase his refcount).

So yes, the RV needs to die, and yes, the sample card will be death for the returned SV * for you.

Your code is error free, but as Joel Berger has shown, you do not need to create an array C beforehand. Its code is also beautiful.

He also showed that if your return type is AV* , the card-card will create a (mortal) link to the array, but it will not be more deadly. So your two main return options

 // Return type = SV* return newRV_noinc(arr); 

and

 // Return type = AV* return MUTABLE_AV(sv_2mortal(MUTABLE_SV(newRV_noinc(arr))); 
+5
source

All Articles