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