bin2cpp is a command line tool for embedding small files (like images, icons or raw data files) into a C++ executable.
When executed, bin2cpp takes binary file as input and outputs c++ code (a function) that when called allows a c++ program to retrieve the content of the input binary file.
Build:
Service/Platform | Build | Tests |
---|---|---|
AppVeyor | ||
Travis CI | ||
Windows Server 2019 | ||
Ubuntu 20.04 | ||
macOS 10.15 |
Statistics:
AppVeyor | Travic CI | GitHub |
---|---|---|
bin2cpp is not implemented using executable resources. Instead, bin2cpp creates a single function call for retrieving the content and the properties of a file which makes it harder to steal the executable's content. It also makes it even harder to replace an existing resource of the executable.
It is designed to be easy to use by developers and to provide easy call functions to get access to the data of the embedded files.
The generated functions that reads and extracts the embedded content does not rely on external libraries so you don't need to setup your projects to use any third party library to start using bin2cpp. All your embedded data can be accessed right away.
The main features of the project are:
- Easily converts small files as C++ source code for embedding into a C++ executable.
- Access content with a unique function call for each embedded file.
- Supports multiple embedded files at once.
- Keep the directory structure when embedding directories.
- Supports encoding and extracting files with a custom directory structure.
- Makes it harder for resource hacker to modify or steal the embedded files.
- No third party libraries required for retrieving the data of the embedded files.
- Supports different types of code generator: string, segment, array, win32 resources.
- File's originals
size
,filename
anddirectory
properties available from generated source code. - Control generated source code: choose your custom File interface and namespace.
- Print a file encoded content to stdout. Useful for scripts and integration with third party application.
- Generated code is C++98 standard-compliant.
The following list show situations where bin2cpp is useful:
- Embedding default configuration files if none are provided.
- Embedding GLSL shaders into the executable.
- Embedding text or XML databases (gui layout, names, dictionaries or localization strings)
- A portable alternative to C++11 raw string literals.
- Prevent stealing copyrighted resources.
- Embedding images/icons/sounds for a GUI application. The application executable can be shipped/copied as a single file.
- Embedding a long PL/SQL code string.
- Allowing an executable to be downloaded from an intranet server as a single file.
- Distributing an application without an installer package. All configurations files and resources can be embedded and extracted at first launch of the application.
The following section shows how to use bin2cpp with code examples:
bin2cpp --file=<path> --output=<path> [--headerfile=<name>] [--identifier=<name>]
[--generator=<name>] [--encoding=<name>] [--chunksize=<value>] [--namespace=<value>]
[--baseclass=<name>] [--managerfile=<name>] [--registerfile]
[--reportedfilepath=<value>] [--override] [--noheader] [--quiet]
bin2cpp --dir=<path> --output=<path> [--keepdirs]
[--generator=<name>] [--encoding=<name>] [--chunksize=<value>] [--namespace=<value>]
[--baseclass=<name>] [--managerfile=<name>] [--registerfile]
[--override] [--noheader] [--quiet]
bin2cpp --help
bin2cpp --version
Argument | Description |
---|---|
--help | Display this help message. |
--version | Display this application version. |
--file=<path> | Path of the input file used for embedding as C++ source code. |
--dir=<path> | Path of the input directory used for embedding all files of the directory as C++ source code. |
--output=<path> | Path of the output directory where to create generated code. ie: ./generated_files |
--headerfile=<name> | File name or relative path of the generated C++ header file. If a relative path from the output directory is specified, the #include statement in the generated cpp file will match the relative path. ie: SplashScreen.h Default value: input file name (without extension) |
--identifier=<name> | Identifier of the function name that is used to get an instance of the file. ie: SplashScreen Default value is based on input file with format 'NameExt'. |
--generator=<name> | Name of the generator to use. Possible values are 'segment', 'string', 'array' and 'win32'. [default: segment] |
--encoding=<name> | Name of the binary to string literal encoding to use. Possible values are 'oct' and 'hex'. [default: oct] |
--chunksize=<value> | Size in bytes of each string segments (bytes per LoC). [default: 200] |
--baseclass=<name> | The name of the interface for embedded files. [default: File] |
--namespace=<name> | The namespace of the generated source code. [default: bin2cpp] |
--reportedfilepath=<path> | The relative reported path of the File. Path returned when calling method getFilePath() of the File class. Automatically calculated when --dir mode is used. ie: images/DCIM/IMG_0001.jpg |
--managerfile=<path> | File name or relative path of the generated C++ header file for the FileManager class. ie: FileManager.h. |
--registerfile | Register the generated file to the FileManager class. This flags is automatically set when parameter 'managerfile' is specified. |
--keepdirs | Keep the directory structure. Forces the output files to have the same directory structure as the input files. Valid only when --dir is used. |
--plainoutput | Print the encoded string in plain format to stdout. Useful for scripts and integration with third party application. |
--override | Tells bin2cpp to overwrite the destination files. |
--noheader | Do not print program header to standard output. |
--quiet | Do not log any message to standard output. |
This example shows how to use bin2cpp to convert a single html file to c++ source code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<title>Hello World!</title>
</head>
<body>
Hello World!
</body>
</html>
bin2cpp.exe --file=helloworld.html --output=.\outdir
bin2cpp v3.0.0 - Convert binary files into C++ source code.
Copyright (C) 2013-2021 end2endzone.com. All rights reserved.
bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp
Embedding "helloworld.html"...
Writing file ".\outdir\helloworld.h"...
Writing file ".\outdir\helloworld.cpp"...
/**
* This file was generated by bin2cpp v3.0.0
* Copyright (C) 2013-2021 end2endzone.com. All rights reserved.
* bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp
* Source code for file 'helloworld.html', last modified 1548537787.
* Do not modify this file.
*/
#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#include <stddef.h>
namespace bin2cpp
{
#ifndef BIN2CPP_EMBEDDEDFILE_CLASS
#define BIN2CPP_EMBEDDEDFILE_CLASS
class File
{
public:
virtual size_t getSize() const = 0;
virtual const char * getFileName() const = 0;
virtual const char * getFilePath() const = 0;
virtual const char * getBuffer() const = 0;
virtual bool save(const char * filename) const = 0;
};
#endif //BIN2CPP_EMBEDDEDFILE_CLASS
const File & getHelloworldHtmlFile();
}; //bin2cpp
#endif //HELLOWORLD_H
/**
* This file was generated by bin2cpp v3.0.0
* Copyright (C) 2013-2021 end2endzone.com. All rights reserved.
* bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp
* Source code for file 'helloworld.html', last modified 1548537787.
* Do not modify this file.
*/
#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "helloworld.h"
#include <string> //for std::string
#include <iostream>
#include <fstream> //for ofstream
namespace bin2cpp
{
class HelloworldHtmlFile : public virtual bin2cpp::File
{
public:
HelloworldHtmlFile() { build(); }
virtual ~HelloworldHtmlFile() {}
virtual size_t getSize() const { return 238; }
virtual const char * getFileName() const { return "helloworld.html"; }
virtual const char * getFilePath() const { return getFileName(); }
virtual const char * getBuffer() const { return mBuffer.c_str(); }
void build()
{
mBuffer.clear();
mBuffer.reserve(getSize()); //allocate all required memory at once to prevent reallocations
mBuffer.append("<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"utf-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=yes\">\r\n <title>Hello World!</title>\r\n</head>\r\n", 200);
mBuffer.append("<body>\r\nHello World!\r\n</body>\r\n</html>", 38);
}
virtual bool save(const char * filename) const
{
std::ofstream f(filename, std::ios::out | std::ios::binary | std::ios::trunc);
if (f.fail()) return false;
size_t fileSize = getSize();
const char * buffer = getBuffer();
f.write(buffer, fileSize);
f.close();
return true;
}
private:
std::string mBuffer;
};
const File & getHelloworldHtmlFile() { static HelloworldHtmlFile _instance; return _instance; }
}; //bin2cpp
At runtime, show file properties and save/export data back to a file.
#include <stdio.h>
#include <string>
#include <iostream>
#include "helloworld.h" //a single include file is all you need
int main(int argc, char* argv[])
{
//get a reference to the embedded file
const bin2cpp::File & resource = bin2cpp::getHelloworldhtmlFile();
//print information about the file.
std::cout << "Embedded file '" << resource.getFileName() << "' is " << resource.getSize() << " bytes long.\n";
//Saving content back to a file.
std::cout << " Saving embedded file to 'helloworld_copy.html'...\n";
bool saved = resource.save("helloworld_copy.html");
if (saved)
std::cout << "saved\n";
else
std::cout << "failed\n";
//Get the internal buffer and do something with the binary data
const char * buffer = resource.getBuffer();
size_t bufferSize = resource.getSize();
//...
return 0;
}
This example shows how to use bin2cpp to convert multiple files of the same directory to c++ source code.
Input directory: samples/demo_icons/flat-color-icons.
The samples/demo_icons/flat-color-icons directory contains the following 56 icons :
These icons are from the Very Basic set of Icons8 Flat Color Icons and are licensed under the Good Boy License.
bin2cpp.exe --dir=flat-color-icons --managerfile=IconsFileManager.h --output=.\outdir --chunksize=50
bin2cpp v3.0.0 - Convert binary files into C++ source code.
Copyright (C) 2013-2021 end2endzone.com. All rights reserved.
bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp
Embedding "flat-color-icons\about.png" using chunks of 50 bytes...
Writing file ".\outdir\about.h"...
Writing file ".\outdir\about.cpp"...
Embedding "flat-color-icons\address_book.png" using chunks of 50 bytes...
Writing file ".\outdir\address_book.h"...
Writing file ".\outdir\address_book.cpp"...
...
Embedding "flat-color-icons\video_file.png" using chunks of 50 bytes...
Writing file ".\outdir\video_file.h"...
Writing file ".\outdir\video_file.cpp"...
Generating "IconsFileManager.h"...
Writing file ".\outdir\IconsFileManager.h"...
Writing file ".\outdir\IconsFileManager.cpp"...
Notice that additional files IconsFileManager.h
and IconsFileManager.cpp
were also generated and will allow retreiving all files at once.
At runtime, show a file listing and save/export the icons files in users temporary directory.
#include <stdio.h> // printf
#include <stdlib.h> // getenv
#include <iostream>
#include "IconsFileManager.h"
int main(int argc, char* argv[])
{
bin2cpp::FileManager & mgr = bin2cpp::FileManager::getInstance();
//Print information about all files generated with "--managerfile" or --registerfile flags.
size_t num_files = mgr.getFileCount();
std::cout << "Found " << num_files << " embedded icons...\n";
//Listing files.
for(size_t i=0; i<num_files; i++)
{
const bin2cpp::File * file = mgr.getFile(i);
std::cout << " File '" << file->getFileName() << "', " << file->getSize() << " bytes\n";
}
//Saving content back to files.
const char * temp_dir = getenv("TEMP");
std::cout << "Saving embedded icons to directory '" << temp_dir << "'...\n";
bool saved = mgr.saveFiles(temp_dir);
if (saved)
std::cout << "saved\n";
else
std::cout << "failed\n";
return 0;
}
Found 56 embedded icons...
File 'about.png', 520 bytes
File 'address_book.png', 1412 bytes
File 'alarm_clock.png', 2334 bytes
File 'audio_file.png', 523 bytes
File 'binoculars.png', 1347 bytes
File 'bookmark.png', 478 bytes
File 'broken_link.png', 1522 bytes
File 'calculator.png', 574 bytes
File 'calendar.png', 574 bytes
File 'cancel.png', 1159 bytes
File 'checkmark.png', 666 bytes
File 'clock.png', 1534 bytes
File 'contacts.png', 626 bytes
...
File 'support.png', 1292 bytes
File 'synchronize.png', 1269 bytes
File 'unlock.png', 718 bytes
File 'upload.png', 467 bytes
File 'video_file.png', 472 bytes
Saving embedded icons to directory 'C:\Users\foobar\AppData\Local\Temp'...
saved
This example shows how to use bin2cpp to generate files in a relative sub directory based on the project's root directory.
Many projects has an include directory located at the project's root directory. These projects are usually configured to add $ROOT_DIR/include to the list of include directories. bin2cpp can be configured to take advantage of this situation.
If you output files in the include directory (with the command --output=$ROOT_DIR/include --headerfile=foo.h
), the generated #include "foo.h"
statement will have no problem finding the generated header. However if you want the generated files to be in a sub directory (for example with the command --output=$ROOT_DIR/include/bin2cpp
), this won't work since you would need the sub directory path in the include statement.
The solution is to specify a relative path for the header file which also changes the generated #include
statement. For example, the command --output=$ROOT_DIR/include --headerfile=bin2cpp/foo.h
), generates #include "bin2cpp/foo.h"
which is perfect since $ROOT_DIR/include
is already an include directory.
This example shows how to specify a relative path for the header file.
bin2cpp.exe --file=res/icon.ico --output=include --headerfile=bin2cpp/file_icon.h --identifier=icon
Note the bin2cpp sub directory in --headerfile=bin2cpp/file_icon.h
. The output sub directory must already exists.
bin2cpp v3.0.0 - Convert binary files into C++ source code.
Copyright (C) 2013-2021 end2endzone.com. All rights reserved.
bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp
Embedding "res/icon.ico"...
Writing file "include/bin2cpp/file_icon.h"...
Writing file "include/bin2cpp/file_icon.cpp"...
Here are the first few generated lines of file file_icon.cpp
.
/**
* This file was generated by bin2cpp v3.0.0
* Copyright (C) 2013-2021 end2endzone.com. All rights reserved.
* bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp
* Source code for file 'icon.ico', last modified 1548537787.
* Do not modify this file.
*/
#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "bin2cpp/file_icon.h"
#include <string> //for std::string
#include <iostream>
#include <fstream> //for ofstream
...
Note the #include "bin2cpp/file_icon.h"
statement which is relative to the project's include directory.
This example shows how to use bin2cpp to convert files from multiple directories to c++ source code. The input directory structure and file location are preserved.
Input directory: samples/demo_website/www.
The samples/demo_website/www directory contains web pages in the following directory structure :
www
├── blog
│ ├── how-to-create-a-web-site
│ │ └── index.html
│ ├── index.html
│ └── using-bin2cpp
│ └── index.html
├── contact
│ └── index.html
├── home
│ └── index.html
└── index.html
The directories above contains multiple files named index.html
.
bin2cpp can create unique identifiers for each files. In case of duplicate identifiers, bin2cpp appends a counter that increases by 1 on every duplicate. The pattern _<counter>
is added to the end where <counter>
is the next counter value. For example, the files above create the following identifiers:
- Indexhtml
- Indexhtml_1
- Indexhtml_2
- Indexhtml_3
- Indexhtml_4
- Indexhtml_5
The same strategy is implemented for duplicate file names.
bin2cpp.exe --dir=www --managerfile=PagesFileManager.h --namespace=www --output=.\outdir --chunksize=50 --keepdirs
Note the --keepdirs
command line option which keep the input directory structure and allows the output files to have the same directory structure as the input files. This prevents duplicate file names.
bin2cpp v3.0.0 - Convert binary files into C++ source code.
Copyright (C) 2013-2021 end2endzone.com. All rights reserved.
bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp
Embedding "www\blog\how-to-create-a-web-site\index.html" using chunks of 50 bytes...
Creating directory ".\outdir\blog\how-to-create-a-web-site"...
Writing file ".\outdir\blog\how-to-create-a-web-site\index.h"...
Writing file ".\outdir\blog\how-to-create-a-web-site\index.cpp"...
Embedding "www\blog\index.html" using chunks of 50 bytes...
Writing file ".\outdir\blog\index.h"...
Writing file ".\outdir\blog\index.cpp"...
Embedding "www\blog\using-bin2cpp\index.html" using chunks of 50 bytes...
Creating directory ".\outdir\blog\using-bin2cpp"...
Writing file ".\outdir\blog\using-bin2cpp\index.h"...
Writing file ".\outdir\blog\using-bin2cpp\index.cpp"...
Embedding "www\contact\index.html" using chunks of 50 bytes...
Creating directory ".\outdir\contact"...
Writing file ".\outdir\contact\index.h"...
Writing file ".\outdir\contact\index.cpp"...
Embedding "www\home\index.html" using chunks of 50 bytes...
Creating directory ".\outdir\home"...
Writing file ".\outdir\home\index.h"...
Writing file ".\outdir\home\index.cpp"...
Embedding "www\index.html" using chunks of 50 bytes...
Writing file ".\outdir\index.h"...
Writing file ".\outdir\index.cpp"...
Generating "PagesFileManager.h"...
Writing file ".\outdir\PagesFileManager.h"...
Writing file ".\outdir\PagesFileManager.cpp"...
Notice that files PagesFileManager.h
and PagesFileManager.cpp
were also generated. They provide support for extracting the content of the embedded www directory.
At runtime, show a file listing and save/export all index.html
files in the right directories.
#include <stdio.h> // printf
#include <stdlib.h> // getenv
#include <iostream>
#include <string>
#include "PagesFileManager.h"
int main(int argc, char* argv[])
{
www::FileManager & mgr = www::FileManager::getInstance();
//Print information about all files generated with "--managerfile" or --registerfile flags.
size_t num_files = mgr.getFileCount();
std::cout << "Found " << num_files << " embedded web pages...\n";
//Listing files.
for(size_t i=0; i<num_files; i++)
{
const www::File * file = mgr.getFile(i);
std::cout << " File '" << file->getFilePath() << "', " << file->getSize() << " bytes\n";
}
//Saving content back to files preserving the original directory structure.
std::string temp_dir = getenv("TEMP");
#ifdef _Win32
temp_dir += "\\";
#else
temp_dir += "/";
#endif
temp_dir += "www";
std::cout << "Saving embedded web pages to directory '" << temp_dir << "'...\n";
bool saved = mgr.saveFiles(temp_dir.c_str());
if (saved)
std::cout << "saved\n";
else
std::cout << "failed\n";
return 0;
}
Found 6 embedded web pages...
File 'index.html', 241 bytes
File 'blog\index.html', 543 bytes
File 'blog\using-bin2cpp\index.html', 4332 bytes
File 'blog\how-to-create-a-web-site\index.html', 3645 bytes
File 'contact\index.html', 2375 bytes
File 'home\index.html', 1422 bytes
Saving embedded web pages to directory 'C:\Users\foobar\AppData\Local\Temp\www'...
saved
The executed code above has extracted the files above with the following directory structure:
C:\Users\username\AppData\Local\Temp\www
├── blog
│ ├── how-to-create-a-web-site
│ │ └── index.html
│ ├── index.html
│ └── using-bin2cpp
│ └── index.html
├── contact
│ └── index.html
├── home
│ └── index.html
└── index.html
bin2cpp v2.4.0 Sample
Demo extraction sample
Please refer to file INSTALL.md for details on how installing/building the application.
bin2cpp has been tested with the following platform:
- Linux, 32 and 64 bit
- Windows, 32 and 64 bit
- macOS, 32 and 64 bit
We use Semantic Versioning 2.0.0 for versioning. For the versions available, see the tags on this repository.
- Antoine Beauchamp - Initial work - end2endzone
See also the list of contributors who participated in this project.
This project is licensed under the MIT License - see the LICENSE file for details