embedded perl in C, perlapio - interoperability with STDIO

僤鯓⒐⒋嵵緔 提交于 2019-12-06 05:38:32

问题


I just realized, that the PerlIO layer seems to do something more than just (more or less) easily wrap the stdio.h-functions. If I try to use a file-descriptor resolved via PerlIO_stdout() and PerlIO_fileno() with functions from stdio.h, this fails.

For example:

PerlIO* perlStdErr = PerlIO_stderr();
fdStdErrOriginal = PerlIO_fileno(perlStdErr);
relocatedStdErr = dup(fdStdOutOriginal);
_write(relocatedStdErr, "something", 8); //<-- this fails

I've tried this with VC10. The embedded perl program is executed from a different context - so it's not possible to use PerlIO from the context where the write to the relocatedStdErr is performed.

For the curious: I need to execute a perl script and forward the output of the script's stdout/stderr to a log whilst keeping the ability to write on stdout for myself. Moreover this should work platform independent (linux, windows console application, win32 desktop application). Just to forward the stdout/stderr doesn't work in Win32 desktop applications since there is none ;) - you need to use the perl's stdout/stderr.

Needed solution: Be able to write on a filehandle (or descriptor) derived from perlio NOT using the PerlIO stack.

EDIT - my solution:

As Story Teller was pointing to PerlIO_findFILE, this did the trick. So here an excerpt of the code - see the comments inside for descriptions:

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 :)

One interesting thing that I actually don't understand is, that the perl documentation says that is't necessary to #define PERLIO_NOT_STDIO 0 to be able to use PerlIO_findFILE(). But for me, that works fine without it and further I like to use PerlIO and the stdio together anyway. That's a point I didn't figured out what is going on.

来源:https://stackoverflow.com/questions/41549508/embedded-perl-in-c-perlapio-interoperability-with-stdio

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!