And*_*oni 12 perl inline-c arrayref
我无法使用Inline C将arrayrefs传递给C函数.我想请一些帮助.
首先,为了证明我可以让Inline C工作,我会将标量值传递给C函数:
#!/usr/bin/perl -I.
#
# try1.pl
#
use Inline C;
my $c = 3.8;
foo( $c );
__END__
__C__
void foo( double c )
{
printf( "C = %f\n", c );
}
Run Code Online (Sandbox Code Playgroud)
并运行它:
% ./try1.pl
C = 3.800000
Run Code Online (Sandbox Code Playgroud)
现在做同样的事情,但使用arrayref:
#!/usr/bin/perl -I.
#
# try2.pl
#
use Inline C;
my @abc = (1.9, 2.3, 3.8);
foo( \@abc );
__END__
__C__
void foo( double *abc )
{
printf( "C = %f\n", abc[2] );
}
Run Code Online (Sandbox Code Playgroud)
运行:
% ./try2.pl
Undefined subroutine &main::foo called at ./try1.pl line 7.
Run Code Online (Sandbox Code Playgroud)
我有什么想法我做错了吗?非常感谢!
fri*_*edo 13
Inline :: C足够智能,可以SV根据你的C函数的类型签名从中提取值.但是如果你想将复杂的Perl结构传递给C函数,你需要使用Perl API来提取值.那么,这是你需要知道的这个问题:
数组是被struct调用的C的实例AV.引用由被struct调用者实现RV.所有这些都是被struct称为基础的"亚型"(有点)SV.
因此,为了使这个功能起作用,我们需要做一些事情.
SV *(指向an的指针SV).SV是否是引用,而不是某种其他类型的标量RV以获得SV它指向的内容.SV是一个数组,所以将它转换为AV并开始使用它.SV.SV我们从数组得到的数值是否适合CprintfSV.所以把它们放在一起,我们得到这样的东西:
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 );
}
Run Code Online (Sandbox Code Playgroud)
Kinda让你欣赏Perl在引擎盖下做了多少工作.:)
现在,您不必像该示例那样超级明确.你可以通过内联做事来摆脱一些临时变量,例如
printf( "C = %f\n", SvNV( *value ) );
Run Code Online (Sandbox Code Playgroud)
将消除宣布的必要性num.但是我想说清楚在C中遍历Perl结构需要多少解除引用和类型检查.
正如@mob在下面指出的那样,你实际上并不需要做所有的工作(尽管熟悉它是如何工作的是一个好主意.)
如果你声明你的函数,Inline :: C足够聪明
void foo( AV *abc ) {
...
}
Run Code Online (Sandbox Code Playgroud)
它将自动AV为您打开包装,您可以直接进入该av_fetch步骤.
如果所有这一切看起来令人困惑,我强烈建议你看看:
perlguts联机帮助页,然后perlapi手册页.数据类型错误。
use Inline 'C';
my @abc = (1.9, 2.3, 3.8);
foo( \@abc );
__END__
__C__
void foo(SV* abc) {
sv_dump(abc);
}
Run Code Online (Sandbox Code Playgroud)