我无法使用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 );
}
运行它:
% ./try1.pl
C = 3.800000
现在做同样的事情,但是使用了一个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] );
}
运行它:
% ./try2.pl
Undefined subroutine &main::foo called at ./try1.pl line 7.
任何想法我做错了什么?非常感谢!
答案 0 :(得分:12)
Inline :: C非常聪明,可以根据您的C函数的类型签名从SV
中提取值。但是如果你想将复杂的Perl结构传递给C函数,你需要使用Perl API来提取值。所以,这是你需要知道的问题:
数组是名为struct
的C AV
的实例。引用由名为struct
的{{1}}实现。所有这些都是名为RV
的基础struct
的“子类型”(有点)。
为了使这个功能起作用,我们需要做一些事情。
SV
(指向SV *
的指针)。 SV
是否为引用,而不是其他某种标量SV
以获取其指向的RV
。SV
是一个数组,因此将其强制转换为SV
并开始使用它。AV
。SV
是否是适合C SV
的数值printf
。所以把它们放在一起,我们得到这样的东西:
SV
有点让你欣赏Perl做了多少工作。 :)
现在,您不必像该示例那样超级明确。你可以通过内联做事来摆脱一些临时变量,例如
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 );
}
将无需声明printf( "C = %f\n", SvNV( *value ) );
。但是我想清楚地说明在C中遍历Perl结构需要多少解除引用和类型检查。
正如@mob在下面指出的那样,你实际上并不需要做所有工作(尽管熟悉它的工作方式是个好主意。)
Inline :: C非常智能,如果你将你的函数声明为
num
它将自动为您打开void foo( AV *abc ) {
...
}
,您可以直接进入AV
步骤。
如果所有这一切看起来令人困惑,我强烈建议你看一下:
perlguts
联机帮助页,然后perlapi
联机帮助页。答案 1 :(得分:4)
错误的数据类型。
use Inline 'C';
my @abc = (1.9, 2.3, 3.8);
foo( \@abc );
__END__
__C__
void foo(SV* abc) {
sv_dump(abc);
}
答案 2 :(得分:4)
在Inline::C代码中:
void foo( SV *reference ) {
AV *array;
array = (AV *)SvRV( reference );
...
}
然后将数组值作为AV
类型处理。请参阅Perl Inline::C Cookbook。