从Perl XS扩展名打印到stdout
|
我最近开始尝试使用XS编写Perl(v5.8.8)扩展。我正在编写的方法之一是收集一堆数据并将其输出到客户端。我想编写一些对输出进行断言的单元测试,但是我遇到了一个问题:似乎PerlIO方法没有通过与Perl中的“ 0”调用相同的通道传递数据。通常,您可以绑定到STDOUT文件处理程序并截取结果,但是PerlIO方法似乎完全绕过了这一点。
我在下面粘贴了一个示例,但是测试的基本原理是:将“ 1”插入“ 2”,运行代码,“ 3”,返回收集的字符串。这样做,我能够捕获
print
语句,但无法捕获模块中的PerlIO_*
调用。我尝试使用PerlIO_write
,PerlIO_puts
,PerlIO_printf
等。没有骰子。
从头开始,这里是我正在做的最小复制:
h2xs -A -n IOTest
cd IOTest
将其放入IOTest.xs
:
#include \"EXTERN.h\"
#include \"perl.h\"
#include \"XSUB.h\"
#include \"ppport.h\"
MODULE = IOTest PACKAGE = IOTest
void
oink ()
CODE:
PerlIO_puts(PerlIO_stdout(), \"oink!\\n\");
然后进入名为test.pl
的文件(有趣的部分在底部附近,其他所有内容仅用于捕获stdout):
# Set up the include path to match the build directories
BEGIN {
push @INC, \'./blib/lib/\';
push @INC, \'./blib/arch/auto/IOTest\';
}
use IOTest;
# This package is just a set of hooks for tieing in to stdout
{
# Lifted from the Test::Output module found here:
# http://search.cpan.org/~bdfoy/Test-Output-1.01/lib/Test/Output.pm
package OutputTie;
sub TIEHANDLE {
my $class = shift;
my $scalar = \'\';
my $obj = shift || \\$scalar;
bless( $obj, $class);
}
sub PRINT {
my $self = shift;
$$self .= join(defined $, ? $, : \'\', @_);
$$self .= defined $\\ ? $\\ : \'\';
}
sub PRINTF {
my $self = shift;
my $fmt = shift;
$$self .= sprintf $fmt, @_;
}
sub read {
my $self = shift;
my $data = $$self;
$$self = \'\';
return $data;
}
}
# Runs a sub, intercepts stdout and returns it as a string
sub getStdOut (&) {
my $callback = shift;
select( ( select(STDOUT), $| = 1 )[0] );
my $out = tie *STDOUT, \'OutputTie\';
$callback->();
my $stdout = $out->read;
undef $out;
untie *STDOUT;
return $stdout;
}
# This is the interesting part, the actual test:
print \"Pre-capture\\n\";
my $output = getStdOut(sub {
print \"before\";
IOTest::oink();
print \"after\";
});
print \"Captured StdOut:\\n\" . $output . \"\\nend\\n\";
这样,构建和测试就可以解决:
perl Makefile.PL
make
perl test.pl
我看到的输出是:
Pre-capture
oink!
Captured StdOut:
beforeafter
end
显然,我希望\“ oink!\\”夹在\“ before \”和\“ after \”之间,但这似乎没有发生。
有任何想法吗?
没有找到相关结果
已邀请:
1 个回复
魄龟呸筹