如何使用Perl XS代码中的绑定文件句柄?

时间:2012-11-29 10:49:01

标签: perl io xs

以下最小示例定义PerlIO_write周围的包装器:

MODULE = My::FH        PACKAGE = My::FH
INCLUDE: const-xs.inc
int
write_fh (SV* fh, SV* str)
CODE:
STRLEN len
char* buf = SvPV(str, len);
PerlIO* io = IoIFP(sv_2io(fh));
if (io) {
    RETVAL = PerlIO_write(io, buf, len);
} else {
    croak("cannot use fh as a PerlIO handle");
}
OUTPUT:
RETVAL

在已创建的文件句柄上使用write_fh函数 使用open $fh, '<', \$buf按预期工作。但是,一个并列 使用以下代码段创建的文件句柄不会变为 PerlIO句柄:

my $fh = Symbol::gensym;
tie *$fh, 'My::TIEFH', \$buf;

My::TIEFH包含所需的方法,并通过print $fh $str向其发送信息与预期一致。

从XS land写入绑定文件句柄需要做什么?

2 个答案:

答案 0 :(得分:1)

print使用call_method

时拨打PRINT
io && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar)))

是真的。放置在堆栈上的受祝福对象是

SvTIED_obj(MUTABLE_SV(io), mg)

顺便说一句,XS编译器可以在CODE的内容之前放置非声明代码,因此CODE的内容不能以声明开头。

CODE:
    STRLEN len
    char* buf = SvPV(str, len);
    PerlIO* io = IoIFP(sv_2io(fh));
    if (io) {
    ...

应该是

CODE:
    {
        STRLEN len
        char* buf = SvPV(str, len);
        PerlIO* io = IoIFP(sv_2io(fh));
        if (io) {
        ...
    }

PREINIT:
    STRLEN len
    char* buf = SvPV(str, len);
    PerlIO* io = IoIFP(sv_2io(fh));
CODE:
    if (io) {
    ...

答案 1 :(得分:0)

尝试理解printpp_hot.c的定义后 并且阅读perlcall(3),我想出了以下内容 码。这有意义吗?

MODULE = My::FH        PACKAGE = My::FH
INCLUDE: const-xs.inc
int
write_fh (SV* fh, SV* str)
INIT:
STRLEN len;
char* buf = SvPV(str, len);
PerlIO* pio = IoIFP(sv_2io(fh));
CODE:
if (pio) {
  RETVAL = PerlIO_write(pio, buf, len);
} else {
  if (!SvROK(fh))
    croak("fh is not a reference");
  IO* io = GvIO(SvRV(fh));
  if (io == NULL)
    croak("fh is not a GLOB reference");
  MAGIC* mg = SvTIED_mg((const SV*)io, PERL_MAGIC_tiedscalar);
  if (mg == NULL)
    croak("fh is not a tied filehandle");
  SV* obj = SvTIED_obj(MUTABLE_SV(io), mg);
  if (obj == NULL) 
    croak("???");
  ENTER;
  SAVETMPS;
  PUSHMARK(SP);
  XPUSHs(obj);
  XPUSHs(str);
  PUTBACK;
  RETVAL = call_method("PRINT", G_SCALAR);
  if (i != 1)
    croak("wrong number of return values (%i)", RETVAL);
  SPAGAIN;
  RETVAL=POPi;
  PUTBACK;
  FREETEMPS;
  LEAVE;
}
OUTPUT:
RETVAL