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 に答える