Discussion:
FILE* to PerlIO*
(too old to reply)
Sisyphus
2006-04-04 01:46:49 UTC
Permalink
Hi,
I guess the succinct way of asking the question is "how do I convert from a
FILE* to a PerlIO* ?".

By way of elaboration, consider the following Inline::C script (which works
fine and as expected):

---------------------
use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

void c_write(FILE * handle) {
fprintf(handle, "hello world\n");
}

EOC

open($wr, '>', 'hello.txt') or die "Opening \$wr: $!";

c_write($wr);

close $wr or die "Closing \$wr: $!";
__END__
-------------------

Suppose now that instead of having the c_write() function write to the
filehandle using fprintf(), I wish it to write using PerlIO_printf(). What
hoops does the c_write() function then have to jump through ?

I'm not sure exactly why I'm asking this question .... I think I'm hoping to
learn something, but I'm not exactly sure what ..... if I learn anything at
all, then I guess that's progress :-)

One thing that puzzles me is that 'perldoc perlclib' recommends using the
PerlIO* types instead of the FILE* types. If that's the recommendation, then
it seems anomalous that perl facilitates the passing of a FILE* from perl to
XS, but not the passing of a PerlIO* from perl to XS. (At least that's the
way it appears to me at the moment.)

Cheers,
Rob
Marvin Humphrey
2006-04-04 02:24:20 UTC
Permalink
Post by Sisyphus
Hi,
I guess the succinct way of asking the question is "how do I
convert from a
FILE* to a PerlIO* ?".
Not sure, but you can open a filehandle in Perl, then get a PerlIO*
out of the scalar like so:

PerlIO *reader = IoIFP( sv_2io(input_filehandle_sv) );
PerlIO *writer = IoOFP( sv_2io(output_filehandle_sv) );

Try this as a demo:

---------------------
use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;
use Inline C => <<'EOC';

void c_write(PerlIO * writer) {
PerlIO_write(writer, "hello world\n", 12);
}

EOC

my $data = '';
open( $wr, '>', \$data ) or die "Opening \$wr: $!";
c_write($wr);
close $wr or die "Closing \$wr: $!";
print $data;
---------------------

Marvin Humphrey
Rectangular Research
http://www.rectangular.com/
Sisyphus
2006-04-04 03:07:14 UTC
Permalink
----- Original Message -----
From: "Marvin Humphrey" <***@rectangular.com>
To: "Sisyphus" <***@optusnet.com.au>
Cc: "xs" <perl-***@perl.org>
Sent: Tuesday, April 04, 2006 12:24 PM
Subject: Re: FILE* to PerlIO*
Post by Marvin Humphrey
Post by Sisyphus
Hi,
I guess the succinct way of asking the question is "how do I
convert from a
FILE* to a PerlIO* ?".
Not sure, but you can open a filehandle in Perl, then get a PerlIO*
PerlIO *reader = IoIFP( sv_2io(input_filehandle_sv) );
PerlIO *writer = IoOFP( sv_2io(output_filehandle_sv) );
Aaah ... thanks for that. (It doesn't answer the question I asked, but it
answers the question I *meant* to ask :-)
.
.
Post by Marvin Humphrey
void c_write(PerlIO * writer) {
PerlIO_write(writer, "hello world\n", 12);
}
.
.
Heh ... I had tried that, but it wouldn't compile. I forget the actual error
I got, but it looked like a syntax error. However, on close visual
inspection of the code I had written (it was only 3 lines !!) I couldn't
spot a syntax error and decided that passing a PERLIO* to XS simply must not
be allowed. Well .... it must have been some silly syntax error after all,
because it works fine, of course :-)

Thanks, Marvin.

Cheers,
Rob
Sherm Pendley
2006-04-04 03:11:15 UTC
Permalink
Post by Sisyphus
One thing that puzzles me is that 'perldoc perlclib' recommends using the
PerlIO* types instead of the FILE* types. If that's the
recommendation, then
it seems anomalous that perl facilitates the passing of a FILE* from perl to
XS, but not the passing of a PerlIO* from perl to XS. (At least that's the
way it appears to me at the moment.)
Does Inline::C use typemaps? If so, then it should be as simple as
just declaring your argument and/or return types as PerlIO* instead
of FILE*. Here's the relevant recipe from ExtUtils/typemap for 5.8.6:

PerlIO * T_INOUT

### INPUT

T_INOUT
$var = IoIFP(sv_2io($arg))

### OUTPUT

T_INOUT
{
GV *gv = newGVgen("$Package");
if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) )
sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
else
$arg = &PL_sv_undef;
}

sherm--

Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
Sisyphus
2006-04-04 04:04:01 UTC
Permalink
----- Original Message -----
From: "Sherm Pendley" <***@dot-app.org>
To: "Sisyphus" <***@optusnet.com.au>
Cc: "xs" <perl-***@perl.org>
Sent: Tuesday, April 04, 2006 1:11 PM
Subject: Re: FILE* to PerlIO*
Post by Sherm Pendley
Post by Sisyphus
One thing that puzzles me is that 'perldoc perlclib' recommends using the
PerlIO* types instead of the FILE* types. If that's the
recommendation, then
it seems anomalous that perl facilitates the passing of a FILE* from perl to
XS, but not the passing of a PerlIO* from perl to XS. (At least that's the
way it appears to me at the moment.)
Does Inline::C use typemaps?
Yep - and it finds the standard typemaps by default.
Unfortunately those typemaps are incapable of counteracting syntax errors in
my xs code. (This is a major inadequacy imho :-)

I had tried passing the arg as a PERLIO*, and when that didn't work I
assumed it was because no such typemap existed. On copying and pasting the
code that Marvin posted, I discovered that I must have made a silly syntax
error in my initial attempts - because it is, in fact, as straightforward,
simple and sensible as it ought to be.

Cheers,
Rob
Nick Ing-Simmons
2006-04-04 21:10:58 UTC
Permalink
Post by Sisyphus
Hi,
I guess the succinct way of asking the question is "how do I convert from a
FILE* to a PerlIO* ?".
I can't remember where I put it, but there is some POD somewhere
which relates to this.

If PerlIO happens to be using :stdio layer you can find the FILE *.
However in general the answer is you can't convert you have to "open"
a new one to the same fileno() as the other.
And once you do that there are lifetime issues (who closes it when).
Post by Sisyphus
By way of elaboration, consider the following Inline::C script (which works
---------------------
use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;
use Inline C => <<'EOC';
void c_write(FILE * handle) {
fprintf(handle, "hello world\n");
}
EOC
open($wr, '>', 'hello.txt') or die "Opening \$wr: $!";
c_write($wr);
close $wr or die "Closing \$wr: $!";
__END__
-------------------
Suppose now that instead of having the c_write() function write to the
filehandle using fprintf(), I wish it to write using PerlIO_printf(). What
hoops does the c_write() function then have to jump through ?
I'm not sure exactly why I'm asking this question .... I think I'm hoping to
learn something, but I'm not exactly sure what ..... if I learn anything at
all, then I guess that's progress :-)
One thing that puzzles me is that 'perldoc perlclib' recommends using the
PerlIO* types instead of the FILE* types. If that's the recommendation, then
it seems anomalous that perl facilitates the passing of a FILE* from perl to
XS, but not the passing of a PerlIO* from perl to XS. (At least that's the
way it appears to me at the moment.)
The PerlIO * mechanism is there...
Post by Sisyphus
Cheers,
Rob
Sherm Pendley
2006-04-05 17:02:28 UTC
Permalink
Post by Nick Ing-Simmons
I can't remember where I put it, but there is some POD somewhere
which relates to this.
"perliol", perhaps?

sherm--

Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org

Loading...