我试图通过Inline :: C编写一个C函数,它将创建并返回一个对Perl的数组引用…下面是我的脚本和输出.我是否正在分配阵列并正确填充它?特别是,我创建一个临时的SV *数组并将它们传递给av_make,并返回用newRV_noinc创建的引用.当我使用Devel :: Peek :: Dump查看返回的数组ref时,引用计数似乎很好,它看起来与直接在perl中创建的相同数据结构相同.
我还不知道什么是mortalization / sv_2mortal,或者我是否需要它.显然,Inline :: C会在返回SV *的函数上自动调用sv_2mortal,这可能与也可能不相关.
#!/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); }
我得到以下输出.
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,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
解决方法
你读过
perldoc perlguts吗?它应该可以帮到你的大部分路. Inline :: C也可以处理AV *返回值.我可能会这样做:
#!/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 some code我写的也可能有所帮助.