如何在程序中包含数据对象文件(图像等)并访问符号?

时间:2022-10-12 22:13:37

I've turned a couple of resource files into .obj files using objcopy and i link them with my programs source code. I can very well access the symbols inside the object file in my program with the following code, but only with GCC/G++ (Cygwin):

我使用objcopy将一些资源文件转换为。obj文件,并将它们与我的程序源代码链接。我可以用下面的代码很好地访问程序中对象文件中的符号,但是只能使用GCC/G++ + (Cygwin):

extern uint8_t data[]   asm("_binary_Resources_0_png_start");
extern uint8_t size[]   asm("_binary_Resources_0_png_size");
extern uint8_t end[]    asm("_binary_Resources_0_png_end");

The code doesn't work in Visual Studio, probably because VS has it's own __asm command. I want to include my programs resources (Images, Shaders, etc.) in my final executable's .data section through linking them.

代码在Visual Studio中不能工作,可能是因为VS有自己的__asm命令。我想通过链接将我的程序资源(图像、着色器等)包含到我最终可执行文件的.data部分中。

But how can i access the symbols defined in the object file in VC++? I tried extern uint8_t _binary_Resources_0_png_start[] or extern "C" uint8_t _binary_Resources_0_png_start[] without the assembly command, but i get unresolved symbol link errors.

但是如何访问vc++中在对象文件中定义的符号?我尝试了外部uint8_t _binary_Resources _0_ png_start[],或在没有装配命令的情况下,将“C”uint8_t _binary_Resources _0_ png_start[],但我得到未解决的符号链接错误。

4 个解决方案

#1


5  

The trick with objcopy isn't meant as a full-featured way to embed resources and isn't portable at all, as you have seen.

objcopy的诀窍并不是一种完整的嵌入资源的方式,它根本就不能移植,正如您所看到的那样。

Microsoft has its own mechanism for resources, so if you're specifically targeting windows, you could use a windows resource file and the RCDATA resource.

微软有自己的资源机制,所以如果你专门针对windows,你可以使用windows资源文件和RCDATA资源。

If you want something completely portable, your only option is to format the file as C sourcecode like e.g.

如果您想要完全可移植的文件,您唯一的选择是将文件格式化为C源代码。

const uint8_t my_binary[] = { 0x00, 0x01, ... }

It's straight forward to write your own conversion tool for that.

为此直接编写自己的转换工具。

#2


5  

It is a may be completely different approach but it provides a rather simple but portable solution:

这可能是一个完全不同的方法,但它提供了一个相当简单但可移植的解决方案:

We use a small tool to load a binary file and output it as C (or C++ source). Actually, I saw things like this in XPM and GIMP but it can be used for rather any binary data.

我们使用一个小工具来加载二进制文件并将其输出为C(或c++源代码)。实际上,我在XPM和GIMP中看到过类似的东西,但是它可以用于任何二进制数据。

To include such tool in the build chain is not difficult in VS, even more simple in make and cmake also.

在VS中包含这样的工具并不困难,在make和cmake中更简单。

Such a tool could look like this:

这样一个工具可以是这样的:

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char **argv)
{
  if (argc < 2) {
    cerr << "Usage: " << argv[0] << " FILE [FILE...]" << endl;
    return -1;
  }
  for (size_t i = 1; i < argc; ++i) {
    fstream fIn(argv[i], ios::in | ios::binary);
    if (!fIn.good()) {
      cerr << "ERROR: Cannot open '" << argv[i] << "'!" << endl;
      continue;
    }
    // make name
    string name = argv[i];
    name = name.substr(0, name.find('.'));
    /// @todo more sophisticated name mangling?
    // print preface
    cout << "struct { const char *data; size_t size; } " << name << " = {" << endl
      << "  \"";
    // print data
    const char hex[] = "0123456789abcdef";
    unsigned char byte;
    enum { BytesPerLine = 16 };
    size_t n = 0;
    for (unsigned char byte; fIn.get((char&)byte); ++n) {
      if (n && !(n % BytesPerLine)) cout << "\"\n  \"";
      cout << "\\x" << hex[byte / 16] << hex[byte % 16];
    }
    // print size
    cout << "\",\n"
      "  " << n << "\n"
      "};" << endl;
  }
  return 0;
}

Compiling and test:

编译和测试:

$ g++ -std=c++11 -o binToC binToC.cc

$ ./binToC
Usage: ./binToC FILE [FILE...]

More testing with fluffy_cat.png 如何在程序中包含数据对象文件(图像等)并访问符号?:

与fluffy_cat更多的测试。png:

$ ./binToC fluffy_cat.png > fluffy_cat.inc

$ cat >fluffy_cat_test.cc <<'EOF'
> #include <fstream>
> 
> using namespace std;
> 
> #include "fluffy_cat.inc"
> 
> int main()
> {
>   ofstream fOut("fluffy_cat_test.png", ios::out | ios::binary);
>   fOut.write(fluffy_cat.data, fluffy_cat.size);
>   fOut.close();
>   return 0;
> }
> EOF

$ g++ -std=c++11 -o fluffy_cat_test fluffy_cat_test.cc

$ ./fluffy_cat_test

$ diff fluffy_cat.png fluffy_cat_test.png

$

As the diff shows – the C source reproduces the original exactly.

正如diff所示,C源准确地再现了原始数据。

Btw. I used the same technique (in similar form) in my answer to SO: Paint a rect on qglwidget at specifit times.

顺便说一句。我使用了相同的技术(以类似的形式)来回答SO:在specifit时间在qglwidget上绘制一个矩形。

#3


2  

Your question originally didn't state whether this is for 64-bit Cygwin G++/MSVC++ or 32-bit. There is a subtle difference when it comes to name decorations.

您的问题最初并没有说明这是针对64位Cygwin G+ /MSVC++还是32位的。在命名装饰方面有一个微妙的区别。


x86 (32-bit Windows PE) solution with OBJCOPY

I'll assume you had a resource file called Resources_0.png. You can generate a 32-bit Windows PE object file with:

我假设您有一个名为Resources_0.png的资源文件。您可以使用以下命令生成一个32位的Windows PE对象文件:

objcopy --prefix-symbol=_ --input-target binary --output-target \
    pe-i386 --binary-architecture i386 Resources_0.png Resources_0.obj

The --prefix-symbol=_ appends an additional underscore (_) to each label. Name decorating with an additional _ is standard for Win32/PE external object. The resulting file would have produced an object with these labels:

前缀符号=_为每个标签添加一个下划线(_)。使用附加_装饰名称是Win32/PE外部对象的标准。产生的文件会产生一个带有这些标签的对象:

__binary_Resources_0_png_start
__binary_Resources_0_png_end
__binary_Resources_0_png_size

MSVC++ and Cygwin G++ targeting 32-bit executables can reference these labels as:

MSVC++和Cygwin G+目标32位可执行文件可以参考以下标签:

extern "C" uint8_t _binary_Resources_0_png_start[];
extern "C" uint8_t _binary_Resources_0_png_end[];
extern "C" uint8_t _binary_Resources_0_png_size[];

x86-64 (64-bit Windows PE) solution with OBJCOPY

You can generate a 64-bit Windows PE object file with:

您可以使用以下命令生成一个64位Windows PE对象文件:

objcopy --input-target binary --output-target pe-x86-64 --binary-architecture i386 \
    Resources_0.png Resources_0.obj

This is similar to the 32-bit however we no longer add an additional underscore (_) before each label. That is because in 64-bit PE code the names aren't decorated with an additional underscore.

这类似于32位,但是我们不再在每个标签之前添加额外的下划线(_)。这是因为在64位的PE代码中,名称没有添加额外的下划线。

The resulting file would have produced an object with these labels:

产生的文件会产生一个带有这些标签的对象:

_binary_Resources_0_png_start
_binary_Resources_0_png_end
_binary_Resources_0_png_size

MSVC++ and Cygwin G++ targeting 64-bit Windows PE executables can reference these labels the exact same was as the 32-bit Windows PE version above:

MSVC++和Cygwin G+针对64位Windows PE可执行文件可以引用这些标签,与上面的32位Windows PE版本完全相同:

extern "C" uint8_t _binary_Resources_0_png_start[];
extern "C" uint8_t _binary_Resources_0_png_end[];
extern "C" uint8_t _binary_Resources_0_png_size[];

Special note: When compiling with MSVC++ as 64-bit code you may end up with this linking error when using the size label:

特别注意:使用MSVC++ +作为64位代码编译时,在使用size标签时可能会出现这个链接错误:

absolute symbol '_binary_Resources_0_png_size' used as target of REL32 relocation in section 4

第4节中将绝对符号“_binary_Resources_0_png_size”用作REL32重定位的目标

With 64-bit code you can avoid this by computing the size in your C++ code by using the difference between the start and end labels like this:

在64位代码中,您可以通过使用像这样的开始和结束标签之间的区别来计算c++代码中的大小,从而避免这一点:

size_t binary_Resources_0_png_size = _binary_Resources_0_png_end - \
                                     _binary_Resources_0_png_start;

Other Observations

Even if using G++/GCC this is bad form:

即使使用g++ /GCC,这也是不好的形式:

extern uint8_t data[]   asm("_binary_Resources_0_png_start");
extern uint8_t size[]   asm("_binary_Resources_0_png_size");
extern uint8_t end[]    asm("_binary_Resources_0_png_end");

There is little need for doing this and it is less portable. See the solutions above that don't use asm directive on variables for G++ code.

几乎没有必要这样做,而且它的可移植性也较差。请参阅上面的解决方案,它们不使用asm指令来处理g++代码中的变量。


The question is tagged both C and C++ and the question contains code with extern "C". The answer above assumes you are compiling .cpp files with G++/MSVC++. If compiling .c files with GCC/MSVC then change extern "C" to extern

这个问题被标记为C和c++,这个问题包含带有extern“C”的代码。上面的答案假设您正在使用g++ /MSVC+编译.cpp文件。如果用GCC/MSVC编译.c文件,那么将extern "C"改为extern


If you want to generate Windows PE objects with OBJCOPY where the data is placed in the read-only .rdata section rather than .data section, you can add this option to the OBJCOPY commands above:

如果您想要使用OBJCOPY生成Windows PE对象,将数据放在只读的.rdata节而不是.data节中,您可以将此选项添加到上面的OBJCOPY命令中:

--rename-section .data=.rdata,CONTENTS,ALLOC,LOAD,READONLY,DATA

I discuss this option in this * answer. The difference being that in Windows PE the read-only section is usually called .rdata where as with ELF objects it is .rodata

我在*的答案中讨论这个选项。与之不同的是,在Windows PE中,只读部分通常被称为.rdata,而在ELF对象中,它是.rodata

#4


0  

After working around and testing different things, i came back to my original approach (linking) and it worked like magic, here is the details:

在研究和测试了不同的东西之后,我回到了我最初的方法(链接),它像魔术一样工作,以下是细节:

In order to include data in the final executable's .data section, you need to first turn that data files (which could be an arbitrary binary file (anything!)) into a linkable file format, also known as an object file.

为了在最终可执行文件的.data部分包含数据,您需要首先将数据文件(可以是任意的二进制文件(任何东西))转换为可链接的文件格式,也称为对象文件。

The tool objcopy which is included in GNU Binutils and is accessible in windows through Cygwin or MinGW, takes a file and produces an object file. objcopy requires two things to know before generating the object file, the output file format and the output architecture. In order to determine these two things, i check a valid linkable object file with the tool objdump:

objcopy工具包含在GNU Binutils中,可以通过Cygwin或MinGW在windows中访问,它获取一个文件并生成一个对象文件。objcopy在生成对象文件、输出文件格式和输出架构之前需要知道两件事情。为了确定这两种情况,我使用工具objdump检查了一个有效的可链接对象文件:

objdump -f main.o

This gives me the following information:

这给了我以下信息:

main.o:     file format pe-x86-64
architecture: i386:x86-64, flags 0x00000039:
HAS_RELOC, HAS_DEBUG, HAS_SYMS, HAS_LOCALS
start address 0x0000000000000000

With this knowledge now i can create the object file:

有了这些知识,我可以创建对象文件:

objcopy -I binary -O pe-x86-64 -B i386 data_file.data data_file_data.o

In order to handle large number of files, batch files could come in handy.

为了处理大量的文件,批处理文件可以派上用场。

I then simply link the produced object file(s) together with my programs source and dereference the pointers that objcopy generated, through the symbols, whose names could easily be queried with:

然后,我简单地将生成的对象文件与我的程序源链接起来,并取消那些通过符号生成的指向对象的指针,这些符号的名称很容易被查询到:

objdump -t data_file_data.o

Which results in:

结果:

data_file_data.o:     file format pe-x86-64

SYMBOL TABLE:
[  0](sec  1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000000 _binary_data_file_data_start
[  1](sec  1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000006 _binary_data_file_data_end
[  2](sec -1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000006 _binary_data_file_data_size

Practically speaking, the following code works with GCC/G++:

实际上,下面的代码适用于GCC/ g++:

extern uint8_t data[]   asm("_binary_data_file_data_start");
extern uint8_t end[]    asm("_binary_data_file_data_end");

And the following with MSVC++:

以下是MSVC++:

extern "C" uint8_t _binary_data_file_data_start[]; // Same name as symbol
extern "C" uint8_t _binary_data_file_data_end[];   // Same name as symbol

The size of each each file is calculated with:

每个文件的大小计算如下:

_binary_data_file_data_end - _binary_data_file_data_start

You could for example write the data back into a file:

例如,你可以将数据写回一个文件:

FILE* file;

file = fopen("data_file_reproduced.data", "wb");
fwrite(_binary_data_file_data_start,                               //Pointer to data
       1,                                                          //Write block size
       _binary_data_file_data_end - _binary_data_file_data_start,  //Data size
       file);

fclose(file);

#1


5  

The trick with objcopy isn't meant as a full-featured way to embed resources and isn't portable at all, as you have seen.

objcopy的诀窍并不是一种完整的嵌入资源的方式,它根本就不能移植,正如您所看到的那样。

Microsoft has its own mechanism for resources, so if you're specifically targeting windows, you could use a windows resource file and the RCDATA resource.

微软有自己的资源机制,所以如果你专门针对windows,你可以使用windows资源文件和RCDATA资源。

If you want something completely portable, your only option is to format the file as C sourcecode like e.g.

如果您想要完全可移植的文件,您唯一的选择是将文件格式化为C源代码。

const uint8_t my_binary[] = { 0x00, 0x01, ... }

It's straight forward to write your own conversion tool for that.

为此直接编写自己的转换工具。

#2


5  

It is a may be completely different approach but it provides a rather simple but portable solution:

这可能是一个完全不同的方法,但它提供了一个相当简单但可移植的解决方案:

We use a small tool to load a binary file and output it as C (or C++ source). Actually, I saw things like this in XPM and GIMP but it can be used for rather any binary data.

我们使用一个小工具来加载二进制文件并将其输出为C(或c++源代码)。实际上,我在XPM和GIMP中看到过类似的东西,但是它可以用于任何二进制数据。

To include such tool in the build chain is not difficult in VS, even more simple in make and cmake also.

在VS中包含这样的工具并不困难,在make和cmake中更简单。

Such a tool could look like this:

这样一个工具可以是这样的:

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char **argv)
{
  if (argc < 2) {
    cerr << "Usage: " << argv[0] << " FILE [FILE...]" << endl;
    return -1;
  }
  for (size_t i = 1; i < argc; ++i) {
    fstream fIn(argv[i], ios::in | ios::binary);
    if (!fIn.good()) {
      cerr << "ERROR: Cannot open '" << argv[i] << "'!" << endl;
      continue;
    }
    // make name
    string name = argv[i];
    name = name.substr(0, name.find('.'));
    /// @todo more sophisticated name mangling?
    // print preface
    cout << "struct { const char *data; size_t size; } " << name << " = {" << endl
      << "  \"";
    // print data
    const char hex[] = "0123456789abcdef";
    unsigned char byte;
    enum { BytesPerLine = 16 };
    size_t n = 0;
    for (unsigned char byte; fIn.get((char&)byte); ++n) {
      if (n && !(n % BytesPerLine)) cout << "\"\n  \"";
      cout << "\\x" << hex[byte / 16] << hex[byte % 16];
    }
    // print size
    cout << "\",\n"
      "  " << n << "\n"
      "};" << endl;
  }
  return 0;
}

Compiling and test:

编译和测试:

$ g++ -std=c++11 -o binToC binToC.cc

$ ./binToC
Usage: ./binToC FILE [FILE...]

More testing with fluffy_cat.png 如何在程序中包含数据对象文件(图像等)并访问符号?:

与fluffy_cat更多的测试。png:

$ ./binToC fluffy_cat.png > fluffy_cat.inc

$ cat >fluffy_cat_test.cc <<'EOF'
> #include <fstream>
> 
> using namespace std;
> 
> #include "fluffy_cat.inc"
> 
> int main()
> {
>   ofstream fOut("fluffy_cat_test.png", ios::out | ios::binary);
>   fOut.write(fluffy_cat.data, fluffy_cat.size);
>   fOut.close();
>   return 0;
> }
> EOF

$ g++ -std=c++11 -o fluffy_cat_test fluffy_cat_test.cc

$ ./fluffy_cat_test

$ diff fluffy_cat.png fluffy_cat_test.png

$

As the diff shows – the C source reproduces the original exactly.

正如diff所示,C源准确地再现了原始数据。

Btw. I used the same technique (in similar form) in my answer to SO: Paint a rect on qglwidget at specifit times.

顺便说一句。我使用了相同的技术(以类似的形式)来回答SO:在specifit时间在qglwidget上绘制一个矩形。

#3


2  

Your question originally didn't state whether this is for 64-bit Cygwin G++/MSVC++ or 32-bit. There is a subtle difference when it comes to name decorations.

您的问题最初并没有说明这是针对64位Cygwin G+ /MSVC++还是32位的。在命名装饰方面有一个微妙的区别。


x86 (32-bit Windows PE) solution with OBJCOPY

I'll assume you had a resource file called Resources_0.png. You can generate a 32-bit Windows PE object file with:

我假设您有一个名为Resources_0.png的资源文件。您可以使用以下命令生成一个32位的Windows PE对象文件:

objcopy --prefix-symbol=_ --input-target binary --output-target \
    pe-i386 --binary-architecture i386 Resources_0.png Resources_0.obj

The --prefix-symbol=_ appends an additional underscore (_) to each label. Name decorating with an additional _ is standard for Win32/PE external object. The resulting file would have produced an object with these labels:

前缀符号=_为每个标签添加一个下划线(_)。使用附加_装饰名称是Win32/PE外部对象的标准。产生的文件会产生一个带有这些标签的对象:

__binary_Resources_0_png_start
__binary_Resources_0_png_end
__binary_Resources_0_png_size

MSVC++ and Cygwin G++ targeting 32-bit executables can reference these labels as:

MSVC++和Cygwin G+目标32位可执行文件可以参考以下标签:

extern "C" uint8_t _binary_Resources_0_png_start[];
extern "C" uint8_t _binary_Resources_0_png_end[];
extern "C" uint8_t _binary_Resources_0_png_size[];

x86-64 (64-bit Windows PE) solution with OBJCOPY

You can generate a 64-bit Windows PE object file with:

您可以使用以下命令生成一个64位Windows PE对象文件:

objcopy --input-target binary --output-target pe-x86-64 --binary-architecture i386 \
    Resources_0.png Resources_0.obj

This is similar to the 32-bit however we no longer add an additional underscore (_) before each label. That is because in 64-bit PE code the names aren't decorated with an additional underscore.

这类似于32位,但是我们不再在每个标签之前添加额外的下划线(_)。这是因为在64位的PE代码中,名称没有添加额外的下划线。

The resulting file would have produced an object with these labels:

产生的文件会产生一个带有这些标签的对象:

_binary_Resources_0_png_start
_binary_Resources_0_png_end
_binary_Resources_0_png_size

MSVC++ and Cygwin G++ targeting 64-bit Windows PE executables can reference these labels the exact same was as the 32-bit Windows PE version above:

MSVC++和Cygwin G+针对64位Windows PE可执行文件可以引用这些标签,与上面的32位Windows PE版本完全相同:

extern "C" uint8_t _binary_Resources_0_png_start[];
extern "C" uint8_t _binary_Resources_0_png_end[];
extern "C" uint8_t _binary_Resources_0_png_size[];

Special note: When compiling with MSVC++ as 64-bit code you may end up with this linking error when using the size label:

特别注意:使用MSVC++ +作为64位代码编译时,在使用size标签时可能会出现这个链接错误:

absolute symbol '_binary_Resources_0_png_size' used as target of REL32 relocation in section 4

第4节中将绝对符号“_binary_Resources_0_png_size”用作REL32重定位的目标

With 64-bit code you can avoid this by computing the size in your C++ code by using the difference between the start and end labels like this:

在64位代码中,您可以通过使用像这样的开始和结束标签之间的区别来计算c++代码中的大小,从而避免这一点:

size_t binary_Resources_0_png_size = _binary_Resources_0_png_end - \
                                     _binary_Resources_0_png_start;

Other Observations

Even if using G++/GCC this is bad form:

即使使用g++ /GCC,这也是不好的形式:

extern uint8_t data[]   asm("_binary_Resources_0_png_start");
extern uint8_t size[]   asm("_binary_Resources_0_png_size");
extern uint8_t end[]    asm("_binary_Resources_0_png_end");

There is little need for doing this and it is less portable. See the solutions above that don't use asm directive on variables for G++ code.

几乎没有必要这样做,而且它的可移植性也较差。请参阅上面的解决方案,它们不使用asm指令来处理g++代码中的变量。


The question is tagged both C and C++ and the question contains code with extern "C". The answer above assumes you are compiling .cpp files with G++/MSVC++. If compiling .c files with GCC/MSVC then change extern "C" to extern

这个问题被标记为C和c++,这个问题包含带有extern“C”的代码。上面的答案假设您正在使用g++ /MSVC+编译.cpp文件。如果用GCC/MSVC编译.c文件,那么将extern "C"改为extern


If you want to generate Windows PE objects with OBJCOPY where the data is placed in the read-only .rdata section rather than .data section, you can add this option to the OBJCOPY commands above:

如果您想要使用OBJCOPY生成Windows PE对象,将数据放在只读的.rdata节而不是.data节中,您可以将此选项添加到上面的OBJCOPY命令中:

--rename-section .data=.rdata,CONTENTS,ALLOC,LOAD,READONLY,DATA

I discuss this option in this * answer. The difference being that in Windows PE the read-only section is usually called .rdata where as with ELF objects it is .rodata

我在*的答案中讨论这个选项。与之不同的是,在Windows PE中,只读部分通常被称为.rdata,而在ELF对象中,它是.rodata

#4


0  

After working around and testing different things, i came back to my original approach (linking) and it worked like magic, here is the details:

在研究和测试了不同的东西之后,我回到了我最初的方法(链接),它像魔术一样工作,以下是细节:

In order to include data in the final executable's .data section, you need to first turn that data files (which could be an arbitrary binary file (anything!)) into a linkable file format, also known as an object file.

为了在最终可执行文件的.data部分包含数据,您需要首先将数据文件(可以是任意的二进制文件(任何东西))转换为可链接的文件格式,也称为对象文件。

The tool objcopy which is included in GNU Binutils and is accessible in windows through Cygwin or MinGW, takes a file and produces an object file. objcopy requires two things to know before generating the object file, the output file format and the output architecture. In order to determine these two things, i check a valid linkable object file with the tool objdump:

objcopy工具包含在GNU Binutils中,可以通过Cygwin或MinGW在windows中访问,它获取一个文件并生成一个对象文件。objcopy在生成对象文件、输出文件格式和输出架构之前需要知道两件事情。为了确定这两种情况,我使用工具objdump检查了一个有效的可链接对象文件:

objdump -f main.o

This gives me the following information:

这给了我以下信息:

main.o:     file format pe-x86-64
architecture: i386:x86-64, flags 0x00000039:
HAS_RELOC, HAS_DEBUG, HAS_SYMS, HAS_LOCALS
start address 0x0000000000000000

With this knowledge now i can create the object file:

有了这些知识,我可以创建对象文件:

objcopy -I binary -O pe-x86-64 -B i386 data_file.data data_file_data.o

In order to handle large number of files, batch files could come in handy.

为了处理大量的文件,批处理文件可以派上用场。

I then simply link the produced object file(s) together with my programs source and dereference the pointers that objcopy generated, through the symbols, whose names could easily be queried with:

然后,我简单地将生成的对象文件与我的程序源链接起来,并取消那些通过符号生成的指向对象的指针,这些符号的名称很容易被查询到:

objdump -t data_file_data.o

Which results in:

结果:

data_file_data.o:     file format pe-x86-64

SYMBOL TABLE:
[  0](sec  1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000000 _binary_data_file_data_start
[  1](sec  1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000006 _binary_data_file_data_end
[  2](sec -1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000006 _binary_data_file_data_size

Practically speaking, the following code works with GCC/G++:

实际上,下面的代码适用于GCC/ g++:

extern uint8_t data[]   asm("_binary_data_file_data_start");
extern uint8_t end[]    asm("_binary_data_file_data_end");

And the following with MSVC++:

以下是MSVC++:

extern "C" uint8_t _binary_data_file_data_start[]; // Same name as symbol
extern "C" uint8_t _binary_data_file_data_end[];   // Same name as symbol

The size of each each file is calculated with:

每个文件的大小计算如下:

_binary_data_file_data_end - _binary_data_file_data_start

You could for example write the data back into a file:

例如,你可以将数据写回一个文件:

FILE* file;

file = fopen("data_file_reproduced.data", "wb");
fwrite(_binary_data_file_data_start,                               //Pointer to data
       1,                                                          //Write block size
       _binary_data_file_data_end - _binary_data_file_data_start,  //Data size
       file);

fclose(file);