我无法使用内联C将arrayrefs传递到C函数中。请寻求帮助。
首先,为了证明我可以使内联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.
有什么想法我做错了吗?帮助极大的赞赏!
最佳答案
Inline::C足够聪明,可以根据C函数的类型签名从SV
提取值。但是,如果要将复杂的Perl结构传递给C函数,则需要使用Perl API提取值。因此,这是您需要解决的问题:
数组是称为struct
的C AV
的实例。引用由称为struct
的RV
实现。所有这些都是称为struct
的基本SV
的“子类型”(种类)。
因此,要使此功能正常工作,我们需要做一些事情。
SV *
(指向SV
的指针)。 SV
是否是引用,而不是其他某种标量RV
以获取其指向的SV
。 SV
是一个数组,请将其转换为AV
并开始使用它。 SV
。 SV
是适合于C的数值printf
SV
中提取实际数值。 因此,将所有这些放在一起,我们得到的是这样的:
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 );
}
Kinda使您欣赏Perl在引擎盖下做了多少工作。 :)
现在,您不必像该示例那样非常明确。您可以通过内联处理来摆脱一些临时变量,例如
printf( "C = %f\n", SvNV( *value ) );
将消除声明
num
的需要。但是我想弄清楚要遍历C语言中的Perl结构需要多少解引用和类型检查。正如@mob在下面指出的那样,您实际上不必做所有的工作(尽管熟悉它的工作方式是个好主意。)
内联:: C非常聪明,如果您将函数声明为
void foo( AV *abc ) {
...
}
它将自动为您解开
AV
,您可以直接进入av_fetch
步骤。如果这一切似乎让您感到困惑,我强烈建议您看一下:
perlguts
联机帮助页,然后perlapi
联机帮助页。 关于Perl内联C : Passing Arrayref to C Function,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18291827/