xcode像windows一样创建命令行窗口

时间:2015-06-30 09:55:23

标签: python c++ xcode windows macos

我有一个Windows应用程序,我用GLFW将其移植到mac。在Win32中,我按::AllocConsole();创建了一个cmd窗口。我用它来调试我的脚本。但是在mac中,似乎无法从正在运行的进度创建cmd窗口。 lldb适用于C ++部分,但对我的python脚本部分没有帮助。我试图创建一个GLFW窗口来伪造它,但GLFW只能运行一个实例,如果我挂断我的应用程序,所有窗口都会暂停。所以,我正在寻找一种在子线程中从我的应用程序创建窗口的方法,它可以用作调试工具与我的应用程序进行交互。

1 个答案:

答案 0 :(得分:0)

Thanks for the excellent question. It took me a moment to work out something that would work on any unix-like system.

Here's a starting point. I'll leave it to others to refine it.

Main points:

  • fork the process into main program and child.

  • main program connects unix-domain socket iostream to a unix socket name of its choice.

  • child process spawns an xterm process which runs the same program with a special command line option, giving it the name of the unix domain socket.

  • spawned version of program running under xterm listens on the unix socket and repeats all data it receives to std out (in the xterm window).

  • original program can now log data to the unix-domain io_stream to emit debugging data.

This program should also work in windows under cygwin.

#include <iostream>
#include <memory>
#include <chrono>
#include <system_error>
#include <thread>
#include <stdlib.h>
#include <unistd.h>

#include <boost/asio.hpp>


using namespace std;

namespace asio = boost::asio;

asio::io_service io_service;
asio::local::stream_protocol::iostream log_stream;

int run_program(int argc, char** argv)
{
    for (int i = 0 ; i < 100 ; ++i) {
        cout << "logging first" << endl;
        log_stream << i << " hello" << endl;
        cout << "logged" << endl;
        this_thread::sleep_for(chrono::milliseconds(400));
    }
    return 0;
}


auto main(int argc, char** argv) -> int
{
    if (argc == 3
        && strcmp(argv[1], "--repeat") == 0)
    {
        auto socket_name = string(argv[2]);

        cout << "listening on " << socket_name << endl;

        ::unlink(socket_name.c_str()); // Remove previous binding.
        asio::local::stream_protocol::endpoint ep(socket_name);
        asio::local::stream_protocol::acceptor acceptor(io_service, ep);
        asio::local::stream_protocol::socket socket(io_service);
        acceptor.accept(socket);
        cout << "accepted" << endl;
        while (1) {
            char buf[100];
            auto bytes_read = socket.read_some(asio::buffer(buf));
            if (bytes_read > 0) {
                cout.write(buf, bytes_read);
                cout.flush();
            }
            else {
                socket.close();
                exit(0);
            }
        }
    }
    else {
        const auto socket_name = "/tmp/foo"s;

        cout << "forking" << endl;
        auto client_pid = fork();
        if (client_pid == 0) {
            cout << "in client" << endl;
            ostringstream ss;
            ss << "xterm -e " << argv[0] << " --repeat " << socket_name;
            auto s = ss.str();
            auto err = system(s.c_str());
            if (err) {
                throw system_error(errno, system_category(), "logger child execution");
            }
        }
        else if (client_pid == -1) {
            throw system_error(errno, system_category(), "forking");
        }
        else {
            cout << "pause to allow xterm client to start" << endl;
            this_thread::sleep_for(chrono::seconds(2));
            cout << "making endpoint " << socket_name << endl;
            asio::local::stream_protocol::endpoint endpoint(socket_name);
            cout << "connecting to " << endpoint << endl;

            log_stream.connect(endpoint);
            cout << "connected" << endl;

            auto ret = run_program(argc, argv);

            log_stream.close();
            exit(ret);
        }
    }
    return 0;
}