Встроенный Perl в C, Perlapio - совместимость с STDIO

Я только что понял, что слой PerlIO, кажется, делает нечто большее, чем просто (более или менее) легко оборачивает stdio.h-функции. Если я пытаюсь использовать файл-дескриптор, разрешенный с помощью PerlIO_stdout() а также PerlIO_fileno() с функциями из stdio.h это не удается.

Например:

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

Я пробовал это с VC10. Встроенная Perl-программа выполняется из другого контекста, поэтому невозможно использовать PerlIO из контекста, в котором выполняется запись в relocatedStdErr.

Для любопытных: мне нужно выполнить Perl-скрипт и перенаправить вывод stdout/stderr скрипта в журнал, сохраняя при этом возможность писать на stdout для себя. Кроме того, это должно работать независимо от платформы (Linux, консольное приложение Windows, настольное приложение Win32). Простая пересылка stdout/stderr не работает в настольных приложениях Win32, так как ее нет;) - вам нужно использовать stlout / stderr из perl.

Необходимое решение: уметь писать на файловом дескрипторе (или дескрипторе), производном от perlio, НЕ используя стек PerlIO.

РЕДАКТИРОВАТЬ - мое решение:

Когда Стори Теллер указывал на 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 Stackru!", 20); //that works :)

Одна интересная вещь, которую я на самом деле не понимаю, это то, что документация Perl говорит, что не нужно #define PERLIO_NOT_STDIO 0 быть в состоянии использовать PerlIO_findFILE(), Но для меня это прекрасно работает без него, и в дальнейшем мне все равно нравится использовать PerlIO и stdio вместе. Это пункт, который я не понял, что происходит.

0 ответов

Другие вопросы по тегам