如何将文件嵌入可执行文件?

Squ*_*all 16 c c++ binary executable file

我有两个问题,第一个问题已经解决了.

当前问题
如果我嵌入了一个需要加载库的文件,例如jpeg图像或mp3音乐,我将需要使用该文件作为库的输入.但是,每个库都是不同的,并使用一种方法来获取文件作为输入,输入可以是文件名或FILE*指针(来自libc的文件界面).

我想知道如何访问带有名称的嵌入式文件.如果我创建一个临时文件,那将是低效的,还有另外一种方法吗?我可以将文件名映射到内存吗?我的平台是Windows和Linux.

如果show_file(const char*name)是库中的函数,我将需要一个字符串来打开该文件.
我已经看到了这些问题:
如何在内存中获取缓冲区的文件描述符?
从C中的文件描述符获取文件名

以下代码是我的解决方案.这是一个好的解决方案吗?它效率低下吗?

# include <stdio.h>
# include <unistd.h>

extern char _binary_data_txt_start;
extern const void* _binary_data_txt_size;
const size_t len = (size_t)&_binary_data_txt_size;

void show_file(const char* name){
    FILE* file = fopen(name, "r");
    if (file == NULL){
        printf("Error (show_file): %s\n", name);
        return;
    }

    while (true){
        char ch = fgetc(file);
        if (feof(file) )
            break;
        putchar( ch );
    }
    printf("\n");

    fclose(file);
}

int main(){

    int fpipe[2];
    pipe(fpipe);

    if( !fork() ){
        for( int buffsize = len, done = 0; buffsize>done; ){
            done += write( fpipe[1], &_binary_data_txt_start + done, buffsize-done );
        }
        _exit(0);
    }

    close(fpipe[1]);
    char name[200];
    sprintf(name, "/proc/self/fd/%d", fpipe[0] );

    show_file(name);

    close(fpipe[0]);
}
Run Code Online (Sandbox Code Playgroud)

另一个问题(已解决)
我尝试在Linux上嵌入一个文件,使用GCC,并且它有效.但是,我尝试在Windows上使用Mingw做同样的事情,并且它没有编译.

代码是:

# include <stdio.h>

extern char _binary_data_txt_start;
extern char _binary_data_txt_end;

int main(){
    for (char* my_file = &_binary_data_txt_start; my_file <= &_binary_data_txt_end; my_file++)
        putchar(*my_file);
    printf("\n");
}
Run Code Online (Sandbox Code Playgroud)

编译命令是:

objcopy --input-target binary --output-target elf32-i386 --binary-architecture i386 data.txt data.o
g++ main.cpp data.o -o test.exe
Run Code Online (Sandbox Code Playgroud)

在Windows上,我收到以下编译器错误:

undefined reference to `_binary_data_txt_start'
undefined reference to `_binary_data_txt_end'
Run Code Online (Sandbox Code Playgroud)

我试图用i386-pc-mingw32替换elf32-i386,但我仍然得到同样的错误.

Mic*_*urr 7

我认为为了使用MinGW,您需要从.c文件中的名称中删除前导下划线.有关详细信息,请参阅使用gcc mingw嵌入二进制blob.

看看是否使用以下帮助:

extern char binary_data_txt_start;
extern char binary_data_txt_end;
Run Code Online (Sandbox Code Playgroud)

如果需要相同的源来使用Linux或MinGW构建,则可能需要使用预处理器在不同的环境中使用正确的名称.


Ada*_*eld 7

如果您使用的库需要FILE*读取数据,那么您可以使用fmemopen(3)从内存blob中创建伪文件.这样可以避免在磁盘上创建临时文件.不幸的是,它是一个GNU扩展,所以我不知道它是否可用于MinGW(可能不是).

但是,大多数编写良好的库(例如libpngIJG的JPEG库)都提供了从内存而不是从磁盘打开文件的例程.特别是libpng甚至提供了一个流接口,您可以在PNG文件完全读入内存之前对其进行递增解码.例如,如果您从网络流式传输隔行扫描的PNG,并且希望在加载时显示隔行数据以获得更好的用户体验,则此功能非常有用.