C++에서 실행 파일에 외부 리소스를 포함하는 방법

8763 단어 cpptutorialcmake
텍스처, 사운드, 정적 데이터 등과 같은 일부 리소스를 프로그램에 포함해야 하는 경우가 매우 많습니다. 일반적으로 프로그램과 함께 파일로 배포합니다. 그러나 응용 프로그램을 단일 실행 파일로 배포하려는 경우 약간 까다로울 수 있습니다.

GCC에 대한 고전적 접근



이를 수행하는 가장 우아한 방법은 설명되어 있습니다here. 완벽하게 작동하지만 GCC가 있는 Linux에서만 작동합니다.

휴대용 접근



리소스를 포함하기 위한 이식 가능한 접근 방식을 원하는 경우cmake를 사용하고 리소스가 문자열인 헤더 파일을 생성할 수 있습니다.

이름이 resource.h.in인 템플릿을 만들어 보겠습니다.

#ifndef RESOURCE_H
#define RESOURCE_H

#include <string_view>
namespace app {

static std::string_view kResource = "@RESOURCE_DATA@";

}
#endif  // RESOURCE_H

CMakeLists.txt에서 파일에서 리소스를 읽고 configure_file를 사용하여 헤더를 생성해야 합니다.

file(READ ${CMAKE_CURRENT_BINARY_DIR}/path/to/resource.data RESOURCE_DATA HEX)
configure_file(resource.h.in ${CMAKE_BINARY_DIR}/app/resource.h @ONLY)


데이터를 16진수로 나타내야 합니다. 지나치게 이진 데이터가 C++ 문자열을 손상시킵니다. 이것은 큰 문제가 아니며 나중에 C++ 코드에서 일반 문자열로 변환할 수 있습니다.

  auto hex_str_to_str = [](std::string hex) {
    auto len = hex.length();
    std::transform(hex.begin(), hex.end(), hex.begin(), toupper);
    std::string new_string;
    for (int i = 0; i < len; i += 2) {
      auto byte = hex.substr(i, 2);
      char chr = ((byte[0] - (byte[0] < 'A' ? 0x30 : 0x37)) << 4) + (byte[1] - (byte[1] < 'A' ? 0x30 : 0x37));
      new_string.push_back(chr);
    }

    return new_string;
  };

auto data = hex_str_to_str(std::move(hex));


안타깝게도 리소스가 크면 Windows에서 다음 오류가 발생할 수 있습니다.

C2026:  string too big, trailing characters truncated


문자열이 16380 chars 보다 크면 발생합니다.
짜증나지만... 문제를 해결하는 것은 가능합니다.
Python에서 문자열의 형식을 다시 지정할 수 있습니다.

"""Script to reformat long string for Windows"""
import sys

STEP = 16000
if __name__ == "__main__":
    filename = sys.argv[1]
    split = []
    with open(filename, "r") as file:
        while True:
            chunk = file.read(STEP)
            split.append(chunk)
            if len(chunk) < STEP:
                break

    with open(filename, "w") as file:
        file.write('"\n"'.join(split))

CMakeLists.txt에서 실행합니다.

file(READ ${CMAKE_CURRENT_BINARY_DIR}/path/to/resource.data RESOURCE_DATA HEX)
configure_file(resource.h.in ${CMAKE_BINARY_DIR}/app/resource.h @ONLY)
execute_process(COMMAND python3 ${CMAKE_SOURCE_DIR}/cmake/split_string.py ${CMAKE_BINARY_DIR}/app/resource.h)


물론 지금 컴퓨터에 Python이 필요합니다. 문제가 되는 경우 pure-CMake에서도 방법을 찾을 수 있습니다.

좋은 웹페이지 즐겨찾기