Windows下使用MSYS2搭建GNU C开发环境


MSYS2


这里先描述搭建成功后,使用yaml库读取配置文件,并借助mmap访问共享内存的实例。

MSYS2的工作界面

编译后执行,是如下效果:


  • 输出内容,类似watch输出
void print_data(const char *old_data, const char *new_data) {
    // 清屏
    printf("\033[H\033[J"); // ANSI 转义序列,清屏

    printf("Data:\n");

    // 获取数据的最大长度
    size_t max_length = strlen(old_data) > strlen(new_data) ? strlen(old_data) : strlen(new_data);

    for (size_t i = 0; i < max_length; i++) {
        // 检查 old_data 和 new_data 的每个字符
        char old_char = (i < strlen(old_data)) ? old_data[i] : ' ';
        char new_char = (i < strlen(new_data)) ? new_data[i] : ' ';

        if (new_char != old_char) {
            // 如果字符不同,标记为红色
            printf("\033[31m%c\033[0m", new_char); // 红色
        } else {
            // 如果字符相同,正常输出
            printf("%c", new_char);
        }
    }
    printf("\n");
}
  • 从yaml格式的文件获取配置

yaml文件内容如下:

file_path: "example.txt"
file_size: 1024
int parse_config(const char *config_path, char **file_path, size_t *file_size) {
    FILE *fp = fopen(config_path, "r");
    if (!fp) {
        perror("Error opening config file");
        return -1;
    }

    yaml_parser_t parser;
    yaml_event_t event;

    if (!yaml_parser_initialize(&parser)) {
        fprintf(stderr, "Failed to initialize parser\n");
        fclose(fp);
        return -1;
    }

    yaml_parser_set_input_file(&parser, fp);

    while(1) {
        if (!yaml_parser_parse(&parser, &event)) {
            fprintf(stderr, "Parser error %d\n", parser.error);
            yaml_event_delete(&event);
            yaml_parser_delete(&parser);
            fclose(fp);
            return -1;
        }

        switch (event.type) {
            case YAML_SCALAR_EVENT:
                if (strcmp((const char *)event.data.scalar.value, "file_path") == 0) {
                    yaml_event_delete(&event);
                    if (!yaml_parser_parse(&parser, &event)) {
                        fprintf(stderr, "Parser error %d\n", parser.error);
                        yaml_event_delete(&event);
                        yaml_parser_delete(&parser);
                        fclose(fp);
                        return -1;
                    }
                    if (event.type == YAML_SCALAR_EVENT) {
                        *file_path = strdup((const char *)event.data.scalar.value);
                    }
                } else if (strcmp((const char *)event.data.scalar.value, "file_size") == 0) {
                    yaml_event_delete(&event);
                    if (!yaml_parser_parse(&parser, &event)) {
                        fprintf(stderr, "Parser error %d\n", parser.error);
                        yaml_event_delete(&event);
                        yaml_parser_delete(&parser);
                        fclose(fp);
                        return -1;
                    }
                    if (event.type == YAML_SCALAR_EVENT) {
                        *file_size = atoi((const char *)event.data.scalar.value);
                    }
                }
                break;
            case YAML_STREAM_END_EVENT:
                printf("YAML_STREAM_END_EVENT received\n");
                break;
            default:
                break;
        }
        if(event.type == YAML_STREAM_END_EVENT){
            yaml_event_delete(&event);
            break;
        }else{
            yaml_event_delete(&event);

        }
    } 

    yaml_parser_delete(&parser);
    fclose(fp);
    return 0;
}
  • 基于文件映射使用共享内存
// Open the file
    fd = open(filename, O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        perror("Error opening file");
        free(filename);
        return EXIT_FAILURE;
    }

    // Set the file size
    if (ftruncate(fd, length) == -1) {
        perror("Error setting file size");
        close(fd);
        free(filename);
        return EXIT_FAILURE;
    }

    // Map the file into memory
    mapped = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (mapped == MAP_FAILED) {
        perror("Error mapping file");
        close(fd);
        free(filename);
        return EXIT_FAILURE;
    }

// Unmap the memory
    if (munmap(mapped, length) == -1) {
        perror("Error unmapping memory");
    }

    // Close the file descriptor
    close(fd);

至于关于在WIndows下搭建GNU C环境的相关问题,如何时、何地、何事、何人、为何、如何、几何,可看如下介绍。

1. What (是什么)

MSYS2 是一个为Windows提供的Unix-like环境的分发和构建平台。它包括一个包管理器(pacman)、一系列GNU工具以及用于编译 和运行C/C++应用程序的开发环境。

2. Why (为什么)

  • 兼容性:MSYS2允许开发者使用常见于Unix-like系统的GNU工具和库,使得从Linux移植应用程序到Windows变得更加简单。
  • 便利性:它提供了一个熟悉的命令行界面和包管理器,简化了开发工具和库的安装与管理。
  • 活跃开发:MSYS2持续维护和更新,确保开发者能够访问最新版本的库和工具。

3. Where (在哪里)

MSYS2可以安装在Windows上,提供的终端环境可以通过开始菜单访问,或者直接通过MSYS2的安装目录访问。它可以与其他Windows开发工具一起使用。

4. When (何时)

开发者可能选择在以下情况下使用MSYS2:

  • 开发需要Unix-like环境的跨平台应用程序。
  • 使用在Windows上本地不可用的特定GNU工具或库。
  • 在Windows上构建或测试主要在Linux上开发的项目。

5. Who (谁)

  • 开发者:熟悉Unix/Linux环境的C/C++开发者,希望在Windows上保持相同的工作流程。
  • 开源贡献者:需要构建和测试主要为Linux开发的软件的贡献者。
  • 学生和学习者:希望在不同操作系统上保持一致开发环境的C/C++编程学习者。

6. How (如何)

  • 安装:从官方网站下载并安装MSYS2。
  • 设置:使用包管理器(pacman)安装所需的开发工具,例如gcc、make以及项目所需的库。
  • 开发:在所选的文本编辑器或IDE中编写C/C++代码,并使用MSYS2终端编译和运行应用程序。

7. How Much (多少)

  • 成本:MSYS2是免费的。通过包管理器提供的工具和库也是开源且免费的。
  • 时间投资:设置MSYS2可能需要几分钟到一小时,具体取决于用户对安装过程的熟悉程度和所需包的数量。

总结

在Windows上使用MSYS2搭建GNU C开发环境提供了兼容性、便利性和广泛的工具访问,使其成为在跨平台环境中工作的开发者的优秀选择 。

参考

  1. https://www.msys2.org/