繁体   English   中英

我如何与Cygwin玩得开心?

[英]How do I play nice with Cygwin?

我有一个C / C ++程序,是为Windows编写的,并使用Visual Studio进行了编译。 而且它是一个命令行工具,这意味着它可以合理地在CyTwin Bash下运行(可能在MinTTY中运行),并且它的某些用户现在正在这样做。

我想更改程序以使其在Cygwin中更好地播放。

我的程序当前使用Windows控制台API输出漂亮的彩色文本并管理光标,并且至少在没有输出时,通常是“交互式的”(对于1980年代的“交互式”定义是“交互式的”)。通过管道传输到文件。

为了使我的程序在Cygwin中更好地发挥作用,我可以使它发出ANSI \\x1B[...转义代码,而不是调用控制台API,但是真正的问题是何时知道这样做


我认为有四种情况:

  1. 作为交互式Windows控制台程序调用。 ->( 使用控制台API。

  2. 作为普通的Windows控制台程序调用,但是用户将其输出传递到某个地方。 ->( 完全不发送样式或交互式呼叫。

  3. 由Bash或在MinTTY下作为交互式程序调用。 ->( 使用ANSI转义码。

  4. 由Bash调用,但用户将其输出传递到某个地方。 ->( 完全不发送样式或交互式呼叫。

我可以通过测试GetConsoleMode()对于stdout句柄是成功还是失败来区分情况1; 如果成功,则肯定有一个Windows控制台,当我打开代码以使用控制台API时就是这种情况。

我想对情况3进行不同的处理,并使用ANSI代码,但不幸的是,情况2、3和4似乎几乎无法区分:

  • 在所有这三种情况下, stdout句柄似乎只是FILE_TYPE_PIPE的不透明对象。
  • 我可以使用OSTYPE环境变量,并且至少可以猜到我在Cygwin的管理之下,该案例将案例2与案例3和4区分开来。
  • 如果我可以链接到cygwin1.dll ,则可以以某种方式使用它的isatty() ,但是我无法链接到cygwin1.dll ,因为许多用户没有(也不会)安装Cygwin。 (即使有可能,我也不敢相信这会奏效 。)
  • MSVC的本机_isatty()认为Cygwin Bash是管道,而不是交互式外壳,因为它只在_isatty()使用了GetFileType()

简而言之,没有明显的方法可以将案例3与案例4分开。

现在,我将情况3和情况2和4完全一样对待,并且Cygwin用户(包括我自己)获得了glass脚的玻璃电传打字交互,而不是友好的交互式全屏显示,我真的很想解决这个问题。


那么,有什么方法可以将交互式 Cygwin调用与其他调用区分开来,从而使我的本机Windows程序在被Cygwin Bash或其他类似Shell调用时表现良好?

重要提示: 一个解决方案,就是假表:该计划将不会被编译为一个本地Cygwin的程序这是一个Windows程序,它的编制与微软的工具链,它不会与GCC编译的。我们的目标是更改/更新它,使其在Cygwin下表现得尽可能好-无需实际链接到任何Cygwin DLL。我只能为Windows合理分发一个可执行文件,而不能合理地分发两个。

如果我可以链接到cygwin1.dll,则可以某种方式使用它的isatty(),但是我无法链接到cygwin1.dll,因为许多用户没有(也不会)安装Cygwin。 (即使有可能,我也不敢相信这会奏效。)

好的,您不能静态链接到该DLL,但这并不意味着您不能尝试动态加载它。

您可以尝试LoadLibrary("cygwin1.dll") 如果失败,则说明它不在cygwin下运行,您可以使用Windows本机功能检测控制台类型。

另一方面,如果您可以打开该库(这意味着Cygwin在当前系统中可用),则可以对isatty()进行动态调用,并使用结果查看输出是否被重定向。

编辑:加载cygwin DLL并调用函数并不是那么容易,您需要首先初始化此链接所示的lib

摘录:

static BOOL setup_root()
{
    HMODULE hCygwin = NULL;

    // Load the cygwin dll into our application.
    if(!load_cygwin_library(&hCygwin))
        return FALSE;

    // Init the cygwin environment. (Required)
    if(!init_cygwin_library(hCygwin))
        return FALSE;

与两个有趣的初始化例程。 如果未调用init_cygwin_library ,则进一步的调用可能不起作用:

static BOOL load_cygwin_library(HMODULE* hCygwin)
{
    if((*hCygwin = GetModuleHandleW(cyglibrary)) == NULL)
        if((*hCygwin = LoadLibraryW(cyglibrary)) == NULL)
            return FALSE;
    return TRUE;
}

static BOOL init_cygwin_library(HMODULE hCygwin)
{
    cygwin_dll_init_fn cygwin_dll_init = NULL;
    if((cygwin_dll_init = (cygwin_dll_init_fn)GetProcAddress(hCygwin,"cygwin_dll_init")) == NULL) {
        FreeLibrary(hCygwin);
        return FALSE;
    }
    cygwin_dll_init();
    return TRUE;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM