-1

この質問の回答で説明されているように、Tcl インタープリターの出力を取得しようとしています。データをファイルに書き込む代わりに、パイプを使用してデータを取得する必要があります。に変更Tcl_OpenFileChannelして Tcl_MakeFileChannel、パイプの書き込み終了を渡しました。その後Tcl_Eval、いくつかのプットでコールしました。パイプの読み取り終了時にデータが来ませんでした。

#include <sys/wait.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <tcl.h>
#include <iostream>

int main() {
    int pfd[2];
    if (pipe(pfd) == -1) { perror("pipe"); exit(EXIT_FAILURE); }
/*
        int saved_flags = fcntl(pfd[0], F_GETFL);
        fcntl(pfd[0], F_SETFL, saved_flags | O_NONBLOCK);
*/

        Tcl_Interp *interp = Tcl_CreateInterp(); 
        Tcl_Channel chan;
        int rc;
        int fd;

        /* Get the channel bound to stdout.
         * Initialize the standard channels as a byproduct
         * if this wasn't already done. */
        chan = Tcl_GetChannel(interp, "stdout", NULL);
        if (chan == NULL) {
                return TCL_ERROR;
        }

        /* Duplicate the descriptor used for stdout. */
        fd = dup(1);
        if (fd == -1) {
                perror("Failed to duplicate stdout");
                return TCL_ERROR;
        }

        /* Close stdout channel.
         * As a byproduct, this closes the FD 1, we've just cloned. */
        rc = Tcl_UnregisterChannel(interp, chan);
        if (rc != TCL_OK)
                return rc;

        /* Duplicate our saved stdout descriptor back.
         * dup() semantics are such that if it doesn't fail,
         * we get FD 1 back. */
        rc = dup(fd);
        if (rc == -1) {
                perror("Failed to reopen stdout");
                return TCL_ERROR;
        }

        /* Get rid of the cloned FD. */
        rc = close(fd);
        if (rc == -1) {
                perror("Failed to close the cloned FD");
                return TCL_ERROR;
        }

        chan = Tcl_MakeFileChannel((void*)pfd[1], TCL_WRITABLE | TCL_READABLE);
        if (chan == NULL)
                return TCL_ERROR;

        /* Since stdout channel does not exist in the interp,
         * this call will make our file channel the new stdout. */
        Tcl_RegisterChannel(interp, chan);



        rc = Tcl_Eval(interp, "puts test");
        if (rc != TCL_OK) {
                fputs("Failed to eval", stderr);
                return 2;
        }

        char buf;
        while (read(pfd[0], &buf, 1) > 0) {
            std::cout << buf;
        }

}
4

1 に答える 1