/ / एक पर्ल XS विस्तार से प्रिंट करने के लिए मुद्रण - पर्ल, पर्ल-मॉड्यूल, एक्सएस

पर्ल प्रति एक्सएल एक्सटेंशन - पर्ल, पर्ल-मॉड्यूल, एक्सएस से स्टडआउट के लिए मुद्रण

मैंने हाल ही में लेखन के साथ खेलना शुरू कियाXS का उपयोग करके पर्ल (v5.8.8) एक्सटेंशन। मेरे द्वारा लिखी जा रही विधियों में से एक डेटा का एक समूह एकत्र करता है और इसे क्लाइंट को देता है। मैं कुछ यूनिट परीक्षणों को लिखना चाहता हूं जो आउटपुट के खिलाफ दावे करते हैं, लेकिन मैं "एक समस्या में चल रहा हूं: यह नहीं है" यह प्रकट होता है कि PerlIO विधियाँ एक ही चैनल के माध्यम से डेटा को गुजर रही हैं print पर्ल में कॉल करता है। आम तौर पर, आप फ़ाइल हैंडलर को STDOUT में बाँध सकते हैं और परिणाम को रोक सकते हैं, लेकिन PerlIO विधियाँ इसे पूरी तरह से दरकिनार करती हैं।

मैंने नीचे एक उदाहरण चिपकाया है, लेकिन मेरे परीक्षण का मूल आधार यह है: Tie करने में STDOUT, भागो कोड, untie, वापसी एकत्र स्ट्रिंग। ऐसा करने से, मैं कब्जा करने में सक्षम हूं 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 (दिलचस्प हिस्सा नीचे के पास है, बाकी सब बस स्टैडआउट को पकड़ने के लिए है)

# 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-capturen";
my $output = getStdOut(sub {
print "before";
IOTest::oink();
print "after";
});
print "Captured StdOut:n" . $output . "nendn";

भवन निर्माण और परीक्षण तब की बात है:

perl Makefile.PL
make
perl test.pl

मैं देख रहा हूँ उत्पादन है:

Pre-capture
oink!
Captured StdOut:
beforeafter
end

जाहिर है, मैं "पहले" और "बाद" के बीच सैंडविच होने की उम्मीद कर रहा हूं, लेकिन ऐसा नहीं हो रहा है।

कोई विचार?

उत्तर:

जवाब के लिए 2 № 1

मुझे लगता है कि कब्जा दोषपूर्ण है। की तुलना करें:

use IOTest;
use Capture::Tiny qw(capture);

print "Pre-capturen";
my $output = capture {
print "before";
IOTest::oink();
print "after";
};
print "Captured StdOut:n" . $output . "nendn";

Pre-capture
Captured StdOut:
beforeoink!
after
end