1

以下最小示例定义了一个包装器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 土地写入绑定的文件句柄?

4

2 回答 2

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) {
    ...
于 2012-11-29T11:16:10.300 回答
0

在尝试理解printinpp_hot.c 和 reading的定义之后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
于 2012-11-30T13:50:33.363 回答