PerlIO レイヤーは、stdio.h 関数を (多かれ少なかれ) 簡単にラップする以上のことをしているように見えることに気付きました。stdio.h の関数を介しPerlIO_stdout()
て解決されたファイル記述子を使用しようとすると、失敗します。PerlIO_fileno()
例えば:
PerlIO* perlStdErr = PerlIO_stderr();
fdStdErrOriginal = PerlIO_fileno(perlStdErr);
relocatedStdErr = dup(fdStdOutOriginal);
_write(relocatedStdErr, "something", 8); //<-- this fails
私はVC10でこれを試しました。埋め込まれた perl プログラムは別のコンテキストから実行されるため、relocatedStdErr への書き込みが実行されるコンテキストから PerlIO を使用することはできません。
好奇心旺盛な方のために: perl スクリプトを実行し、スクリプトの stdout/stderr の出力をログに転送する必要があります。さらに、これはプラットフォームに依存せずに動作するはずです (Linux、Windows コンソール アプリケーション、win32 デスクトップ アプリケーション)。stdout/stderr を転送するだけでは、Win32 デスクトップ アプリケーションでは動作しません。それがないためです ;) - perl の stdout/stderr を使用する必要があります。
必要な解決策: PerlIO スタックを使用せずに perlio から派生したファイルハンドル (または記述子) に書き込むことができるようにします。
編集 - 私の解決策:
Story Teller が PerlIO_findFILE を指していたので、これでうまくいきました。ここにコードの抜粋があります - 説明については、内部のコメントを参照してください。
FILE* stdErrFILE = PerlIO_findFILE(PerlIO_stderr()); //convert to Perl's stderr to stdio FILE handle
fdStdErrOriginal = _fileno(stdErrFILE); //get descriptor using MSVC
if (fdStdErrOriginal >= 0)
{
relocatedStdErr = _dup(fdStdErrOriginal); //relocate stdErr for external writing using MSVC
if (relocatedStdErr >= 0)
{
if (pipe(fdPipeStdErr) == 0) //create pipe for forwarding stdErr - USE PERL's IO since win32subsystem(non-console) "_pipe" doesn't work
{
if (dup2(fdPipeStdErr[1], fdStdErrOriginal) >= 0) //hang pipe on stdErr - USE PERL's IO (since it's created by perl)
{
close(fdPipeStdErr[1]); //close the now duplicated writer on stdErr for further usage - USE PERL's IO (since it's created by perl)
//"StreamForwarder" creates a thread that catches/reads the pipe's input and forwards it to the processStdErrOutput function (using the PerlIO)
stdErrForwarder = new StreamForwarder(fdPipeStdErr[0], &processStdErrOutput, PerlIO_stderr());
return relocatedStdErr; //return the relocated stdErr to be able to '_write' onto it
}
}
}
}
...
...
_write(relocatedStdErr, "Hello Stackoverflow!", 20); //that works :)
#define PERLIO_NOT_STDIO 0
私が実際に理解していない興味深いことの 1 つは、perl のドキュメントでは、PerlIO_findFILE()
. しかし、私にとっては、それがなくても問題なく動作し、さらに、とにかく PerlIO と stdio を一緒に使用するのが好きです。何が何だか分からなかった点です。