How can I support autovivified filehandle arguments in an XS function?
I'm XS-wrapping a C function which returns a file descriptor, and I'd like to present that file descriptor as a perl filehandle argument in the manner of open(). E.g.,
myfunc(my $fh) or die "Error: $!";
do_something_with_fh($fh);
Right now I'm using a perl wrapper on top of the XS function:
# -- in perl
sub myfunc {
my $fd = _myfunc();
return open($_[0], '+<&=', $fd) if defined($fd);
}
/* -- in XS */
SysRet
_myfunc()
CODE:
RETVAL = some_c_function_returning_an_fd();
OUTPUT:
RETVAL
This works Just Fine (tm), but, again, I'd like to move the implementation entirely into XS.
So far I've tried sv_2io
on an argument typemapped as SV *
, but that throws an exception on undefined scalars. I have not tried mapping the first argument to a FILE *
or PerlIO *
object, since I don't know how I'd "fdreopen" (if you will) those objects.
I would keep the myfunc()
wrapper in Perl, it works and shouldn't be a bottleneck.
Reimplementing open()
is tricky and requires usage of undocumented/internal API. I think this is a pretty close implementation. newGVgen()
and do_openn()
is part of the public API but undocumented and subject to change.
void
myfunc(sv)
SV *sv
PPCODE:
{
GV *gv = newGVgen("Mypackage");
SV *rv = sv_2mortal(newRV_noinc((SV *)gv));
SV *fd = sv_2mortal(newSViv(some_c_function_returning_an_fd()));
if (!do_openn(gv, "+<&=", 4, FALSE, 0, 0, NULL, &fd, 1))
croak("Could not fdopen descriptor: '%s'", Strerror(errno)); /* or XSRETURN_NO; */
sv_setsv(sv, rv);
SvSETMAGIC(sv);
XSRETURN_YES;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With