从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 \”之间,但这似乎没有发生。 有任何想法吗?     
已邀请:
我认为捕获是错误的。比较:
use IOTest;
use Capture::Tiny qw(capture);

print \"Pre-capture\\n\";
my $output = capture {
    print \"before\";
    IOTest::oink();
    print \"after\";
};
print \"Captured StdOut:\\n\" . $output . \"\\nend\\n\";
Pre-capture
Captured StdOut:
beforeoink!
after
end
    

要回复问题请先登录注册