c - 在静态库中嵌入资源 - C/C++

标签 c resources static-libraries archive

我正在学习如何仅使用终端创建库。是否有可能(我怀疑可能不可能)将资源(例如图像、文本、API key 等)放入静态链接的存档文件中,就像在 NSBundle 中一样?我如何引用这些资源?

最佳答案

在 POSIX 系统上,您有一个几乎标准的 shell sh ,四个非常有用的 shell 实用程序,名为 rm , printf , od ,和sed .

假设您希望使用包含二进制文件 foo.bar 内容的 const unsigned char blob[] 数组创建文件 foo.c:

export LANG=C LC_ALL=C
rm -f foo.c
printf 'const unsigned char blob[] = {\n' > foo.c
od -A n -t x1 foo.bar | sed -e 's| *\([0-9A-Fa-f][0-9A-Fa-f]\)| 0x\1U,|g; s|^|   |' >> foo.c
printf '};\n' >> foo.c

第一行将语言环境设置为C。这确保实用程序使用我们期望的格式,而不是某些本地化变体。

第二行删除可能存在的foo.c。 (如果您将输出直接输出到现有文件而不附加到它,有些 shell 会提示。)如果文件还不存在,-f 会消除任何提示。

第三行和第五行将数组定义附加到 foo.c 文件中。

第四行使用od实用程序将foo.bar的内容输出为十六进制字节。我们使用 sed 在每个十六进制字节前面添加 0x 和附加 U, 使其变得漂亮且漂亮的 C,然后我们在前面添加额外的三个该行的空格(使其缩进四个空格)。

如果您不喜欢这种方法,您可以随时编写自己的实用程序来完成此操作。例如: #包括 #包括 #包括 #包括

#ifndef  DEFAULT_VARNAME
#define  DEFAULT_VARNAME "blob"
#endif

#ifndef  DEFAULT_STORAGE
#define  DEFAULT_STORAGE "const"
#endif

#ifndef  DEFAULT_ATTRIBUTES
#define  DEFAULT_ATTRIBUTES ""
#endif

#ifndef  DEFAULT_INDENT
#define  DEFAULT_INDENT "    "
#endif

#ifndef  DEFAULT_COLUMNS
#define  DEFAULT_COLUMNS 16
#endif

int usage(const char *argv0)
{
    fprintf(stderr, "\n");
    fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv0);
    fprintf(stderr, "       %s [ OPTIONS ] file [ [ OPTIONS ] file .. ]\n", argv0);
    fprintf(stderr, "\n");
    fprintf(stderr, "Options:\n");
    fprintf(stderr, "       -n %-10s Variable name\n", "'" DEFAULT_VARNAME "'");
    fprintf(stderr, "       -s %-10s Storage type\n", "'" DEFAULT_STORAGE "'");
    fprintf(stderr, "       -a %-10s Attributes\n", "'" DEFAULT_ATTRIBUTES "'");
    fprintf(stderr, "       -i %-10s Indentation\n", "'" DEFAULT_INDENT "'");
    fprintf(stderr, "       -c %-10d Bytes per line\n", (int)DEFAULT_COLUMNS);
    fprintf(stderr, "\n");
    fprintf(stderr, "This program will output the contents of the specified file(s)\n");
    fprintf(stderr, "as C source code.\n");
    fprintf(stderr, "\n");
    return EXIT_SUCCESS;
}


int main(int argc, char *argv[])
{
    const char *storage = DEFAULT_STORAGE;
    const char *varname = DEFAULT_VARNAME;
    const char *attributes = DEFAULT_ATTRIBUTES;
    const char *indent = DEFAULT_INDENT;
    size_t      columns = DEFAULT_COLUMNS;

    FILE   *in;
    size_t  bytes;
    int     ch, arg;
    char    dummy;

    if (argc < 2)
        return usage(argv[0]);

    arg = 1;
    while (arg < argc) {

        if (argv[arg][0] == '-') {
            if (argv[arg][1] == 'n') {
                if (argv[arg][2] != '\0') {
                    varname = argv[arg] + 2;
                    arg++;
                    continue;
                } else
                if (arg + 1 < argc) {
                    varname = argv[arg + 1];
                    arg += 2;
                    continue;
                }
            } else
            if (argv[arg][1] == 's') {
                if (argv[arg][2] != '\0') {
                    storage = argv[arg] + 2;
                    arg++;
                    continue;
                } else
                if (arg + 1 < argc) {
                    storage = argv[arg + 1];
                    arg += 2;
                    continue;
                }
            } else
            if (argv[arg][1] == 'a') {
                if (argv[arg][2] != '\0') {
                    attributes = argv[arg] + 2;
                    arg++;
                    continue;
                } else
                if (arg + 1 < argc) {
                    attributes = argv[arg + 1];
                    arg += 2;
                    continue;
                }
            } else
            if (argv[arg][1] == 'i') {
                if (argv[arg][2] != '\0') {
                    indent = argv[arg] + 2;
                    arg++;
                    continue;
                } else
                if (arg + 1 < argc) {
                    indent = argv[arg + 1];
                    arg += 2;
                    continue;
                }
            } else
            if (argv[arg][1] == 'c') {
                if (argv[arg][2] != '\0') {
                    if (sscanf(argv[arg] + 2, " %zu %c", &columns, &dummy) != 1 || columns < 1) {
                        fprintf(stderr, "%s: Invalid number of bytes per line.\n", argv[arg] + 2);
                        return EXIT_FAILURE;
                    }
                    arg++;
                    continue;
                } else
                if (arg + 1 < argc) {
                    if (sscanf(argv[arg+1], " %zu %c", &columns, &dummy) != 1 || columns < 1) {
                        fprintf(stderr, "%s: Invalid number of bytes per line.\n", argv[arg + 1]);
                        return EXIT_FAILURE;
                    }
                    arg += 2;
                    continue;
                }
            } else
            if (!strcmp(argv[arg], "-h") || !strcmp(argv[arg], "--help"))
                return usage(argv[0]);
        }

        in = fopen(argv[arg], "r");
        if (!in) {
            fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
            return EXIT_FAILURE;
        }

        printf("%s unsigned char %s[] %s= {", storage, varname, attributes);

        bytes = 0;
        while ((ch = getc(in)) != EOF)
            if (bytes++ % columns)
                printf(", %3u", (unsigned int)ch);
            else
                printf("\n%s%3u", indent, (unsigned int)ch);

        printf("\n}; /* %zu bytes */\n\n", bytes);

        if (ferror(in)) {
            fclose(in);
            fprintf(stderr, "%s: Read error.\n", argv[arg]);
            return EXIT_FAILURE;
        }
        if (fclose(in)) {
            fprintf(stderr, "%s: Delayed read error.\n", argv[arg]);
            return EXIT_FAILURE;
        }

        if (fflush(stdout) || ferror(stdout)) {
            fprintf(stderr, "Error writing to standard output.\n");
            return EXIT_FAILURE;
        }

        arg++;
    }

    return EXIT_SUCCESS;
}

上述代码中唯一的 POSIX 主义是使用 %zu 扫描并打印 size_t

关于c - 在静态库中嵌入资源 - C/C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36098868/

相关文章:

Python - Py_Initialize 在编译期间未解析

c++ - 使用库时运行时检查失败 #0

c - 我想使用 memset 从字符串中删除一些字符

c - 给定示例中线程特定的数据混淆

javascript - 如何在 Grails Resources Plugin 中指定通配符资源模式?

Spring 4 基于注解的静态资源映射等效项

linux - 为另一台服务器编译 gawk 可执行文件

c - 测试 Float 值是否为 NaN

c - 错误 :declaration terminated incorrectly

ruby-on-rails - Ruby on Rails : singular resource and form_for