私は、書き込み可能なストリームインターフェイスとして、 Perlコードにライブラリを公開するXSコードを書くことを試みています。以下の関数 get_stream
は、 がPerlIOオブジェクトを準備して返すコンストラクタであると考えられます。私は Write
とClose
の方法しか必要ないと思ったので、他のすべての機能スロットは空白にしました。PerlIO *をリークするこのXSコードはなぜですか?
typedef struct {
struct _PerlIO base;
mylib_context* ctx;
} PerlIOmylib;
/* [...] */
PERLIO_FUNCS_DECL(PerlIO_mylib_funcs) = {
.fsize = sizeof(PerlIO_funcs),
.name = "mylib",
.size = sizeof(PerlIOmylib,
.Write = mylib_write,
.Close = mylib_close,
};
/* XS below */
PerlIO*
get_stream (SV* context_obj)
CODE:
mylib_context* ctx = (mylib_context*) SvIV (SvRV (context_obj));
PerlIO* f = PerlIO_allocate (aTHX);
f = PerlIO_push (aTHX, f, PERLIO_FUNCS_CAST(&PerlIO_mylib_funcs), "a", NULL);
PerlIOSelf(f, PerlIOmylib)->ctx = ctx;
PerlIOBase(f)->flags |= PERLIO_F_OPEN;
RETVAL = f;
OUTPUT:
RETVAL
私はこのような提供するインタフェースを使用する場合...
{
my $fh = MyLib::get_stream($lib_ctx);
print $fh "x" x 300;
}
... mylib_write
関数が呼び出されますので、私は完全に がこれまでめちゃくちゃにしていません。 (私はこれを確認してデバッグprintf ステートメントを挿入して検証しました)しかし、 $fh
が範囲外になるとPerlIOオブジェクトが閉じられるようにしたいのですが、 ファイルハンドルをopen
で作成したものと同じです。しかし、現時点では、mylib_close
関数はインタープリタのシャットダウン時にのみ呼び出されます。
close
を直接呼び出すと、$fh
~undef
は に設定されます。
UPDATE:は池上のアドバイスの後、私はDevel::Peek::Dump
とsv_dump
を使用し、ハンドルがget_stream
機能がSV = PVGV(...)
を指して「RV」 で返されたことが分かりました。グロブ(PVGV
)の リファレンスカウンタは3に設定されていますが、これは正しくないようです。 $fh
は、ブロックの最後でスコープ外になったときclose
関数が呼び出されます。
CLEANUP:
SvREFCNT_dec (SvRV (ST(0)));
SvREFCNT_dec (SvRV (ST(0)));
を追加しました。しかし、私はまだ基本的な問題を理解しているとはまだありません。
これはOUTPUT
セクションのために生成されたCコードです:
ST(0) = sv_newmortal();
{
GV *gv = newGVgen("MyLib");
if (do_open(gv, "+<&", 3, FALSE, 0, 0, RETVAL))
sv_setsv(ST(0), sv_bless(newRV((SV*)gv), gv_stashpv("MyLib",1)));
else
ST(0) = &PL_sv_undef;
}
XSRETURN(1);
どのようにGVの参照カウントが3で終わるのでしょうか?
UG、同じポストでは同じで、まったく新しい質問 – ikegami