gpt4 book ai didi

Xcode 和 Curses.h 打开终端时出错

转载 作者:行者123 更新时间:2023-12-02 11:23:30 25 4
gpt4 key购买 nike

我正在尝试使用 Xcode 编译一个简单的诅咒项目。
该程序可以在带有 -lcurses 标志的终端中使用 g++ 进行良好编译,并且运行良好。

首先创建一个 c++ 类型的命令行工具。
将curses.h导入到我的main中。
在Tar​​get“program”Info -> General -> Linked Libraries中,已添加libCurses.dylib。

编译正常,但终端窗口无法打开。
在调试控制台中,输出为

程序已加载。
运行
[切换到进程3424]
打开终端时出错:未知。
正在运行...

我可以进入构建文件夹,然后在终端中打开程序,但是 xcode 有什么方法可以打开终端吗?

感谢您的帮助!

最佳答案

我在 Xcode 中调试 ncurses 时遇到了同样的问题。最后,我找到了一种使用 Terminal.app 管理调试的好方法,该应用允许调试 ncurses。

众所周知,要初始化和使用 ncurses,我们需要在终端中运行我们的应用程序。但是当我们按下运行按钮时,Xcode 不会打开终端。因此,如果我们从代码中请求环境变量TERM,我们将得到NULL。这就是应用程序在 initscr() 上崩溃的原因。

因此,需要启动 Terminal.app,在那里执行我们的进程并附加一个调试器。可以通过Scheme设置来实现。我是在 Xcode 11.4 中完成的。我基于 Language: C++ 创建了一个新的 macOS 命令行工具项目。此外,我还在框架和库中添加了libncurses.tbd依赖项。

转至产品 > 方案 > 编辑方案...,选择运行方案和运行操作,然后导航至信息 选项卡。您会看到Launch 设置为Automatically。将其更改为等待可执行文件启动enter image description here

Run方案中选择Pre-actions并添加New Run Script Action。将 Provide build settings fromNone 更改为您的构建目标。在那里添加以下代码:

osascript -e 'tell application "Terminal"' -e 'delay 0.5' -e 'activate' -e "do script (\"$TARGET_BUILD_DIR/$PRODUCT_NAME\")" -e 'end tell' &

enter image description here

要选择在调试 session 结束时关闭终端,请选择 Run 方案中的 Post-actions 并添加新运行脚本操作。添加以下代码:

osascript -e 'activate application "Terminal"' -e 'delay 0.5' -e 'tell application "System Events"' -e 'tell process "Terminal"' -e 'keystroke "w" using {command down}' -e 'end tell' -e 'end tell'

enter image description here实际上,osascript 将始终创建至少两个终端窗口,但如果您将第一个窗口保持打开状态,它将通过“前置”和“后置”操作自动创建和销毁第二个终端窗口。

您可能还会遇到调试器附加问题。我不知道 Xcode 在进程外部执行时不想附加调试器的确切原因,但我发现了这个问题。此外,我还发现在调试 session 开始期间 stdin 流处于奇怪的状态。因此,我编写了一个基于 pselect 调用的解决方法。我向 stdin 请求任何数据,直到它没有返回成功。我发现在这些操作之后,调试器会感觉正常,并且 stdin 请求也会正常。这是我的代码示例:

#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>

bool g_has_terminal = false; // Check this global variable before ncurses calls

bool ensure_debugger_attached_woraround(int timeout_ms)
{
fd_set fd_stdin;
FD_ZERO(&fd_stdin);
FD_SET(STDIN_FILENO, &fd_stdin);
struct timespec timeout = { timeout_ms / 1000, (timeout_ms % 1000) * 1000000 };

do
{
errno = 0;
}
while (pselect(STDIN_FILENO + 1, &fd_stdin, NULL, NULL, &timeout, NULL) < 0 && errno == EINTR);

if (errno != 0)
{
fprintf(stderr, "Unexpected error %d", errno);
return false;
}

return true;
}

int main(int argc, const char *argv[])
{
if (!ensure_debugger_attached_woraround(700))
return 1;

char *term = getenv("TERM");

g_has_terminal = (term != NULL);

if (g_has_terminal)
g_has_terminal = (initscr() != NULL);

// Some ncurses code. Maybe you should terminate if g_has_terminal is not set

if (g_has_terminal)
{
printw("Press any key to exit...");
refresh();

getch();

endwin();
}

return 0;
}

ensure_debugger_attached_woraround 的调用超时时间为 700 毫秒。我尝试了不同的值,发现 500 毫秒是不跳过 pselect 的最小时间。也许这个超时是由机器决定的,我不知道。您可以通过#ifdef ... #endif 或其他一些检查来包装此调用,也许可以通过特殊的命令行参数检查来排除 Release模式中的一点等待开销。

关于Xcode 和 Curses.h 打开终端时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4919373/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com