DCMTK 3.6.7 버전을 VisualStudio 2022로 빌드하는 방법에 대해 알아봅니다.

 

 

 

0. Pre-compiled Libs

 

vcpkg를 이용하면 간단히 pre-compiled libs를 다운로드할 수 있습니다. 

 

 

다만, 검색하면 3.6.7 버전으로 나오지만 실제 install을 시도하면 3.6.6#3 버전이 다운로드됩니다.

 

 

 

1. Source code 및 라이브러리 다운로드

 

DCMTK 공식 홈페이지로 이동해 소스코드를 다운로드합니다.

 

https://dicom.offis.de/en/dcmtk/dcmtk-software-development/

 

Software Development based on DCMTK - dicom.offis.de

DCMTK 3.6.7 Documentation in HTML Format (25,144 KiB)

dicom.offis.de

 

위 페이지에서 DCMTK 3.6.7 - Source Code and Documentation (2022-04-28)에 해당하는 소스 코드를 다운로드합니다.

 

이후 동일 페이지 아래에 있는 DCMTK 3.6.7 - Support Libraries for Windows에서 필요한 라이브러리를 다운로드합니다.

 

이 글에선 VisualStudio 17 2022에서 "MD" 옵션으로 DCMTK를 빌드할 예정이므로 다음 파일을 다운로드합니다:  "Pre-compiled libraries for Visual Studio 2022 (MSVC 17.0), 64 bit, with icu4c, with "MD" option"

 

 

 

2. CMake Configure & Generate

 

편하게 CMake gui를 열고 소스코드와 빌드폴더를 지정합니다.

 

이후 Configure 버튼을 클릭해 VisualStudio 17 2022와 x64를 선택한 뒤 구성을 진행합니다.

 

 

구성이 완료된 뒤 위와 같이 Advanced 체크박스를 클릭해 모든 옵션을 확인합니다.

 

다음과 같이 구성을 "MT"에서 "MD"로 변경합니다.

 

 

이와 함께 "DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS"를 체크해제 합니다. 해당 옵션이 체크되어 있으면 기껏 바꾼 MD옵션이 무시됩니다.

 

 

이제 라이브러리를 연결합니다. 다음과 같이 필요한 라이브러리를 선택해 줍니다.

 

 

선택한 라이브러리가 위치한 경로를 지정합니다.

 

해당 경로는 앞서 받은 라이브러리를 압축 해제한 경로를 지정해 주면 됩니다.

 

저는 사진과 같이 dcmtk 소스 폴더 내에 external 폴더를 만든 뒤 그 안에 압축을 해제해 두었습니다.

 

여기까지 완료되면 이제 Generate 버튼을 클릭해 VisualStudio 17 2022를 위한 sln 파일을 생성합니다.

 

 

 

3. Solution builld.

 

CMake에서 Generate가 완료된 뒤 빌드 폴더로 이동하면 sln 파일이 생성된 걸 확인할 수 있습니다.

 

 

해당 파일을 열어 ALL_BUILD 프로젝트를 빌드합니다.

 

 

빌드가 정상적으로 진행되는 것을 확인할 수 있습니다.

 

 

제가 구성한 코드는 다음 깃헙 페이지에서 확인할 수 있습니다: smoh-dev/dcmtk-3.6.7

 

GitHub - smoh-dev/dcmtk-3.6.7: Built VS17 with MD option.

Built VS17 with MD option. Contribute to smoh-dev/dcmtk-3.6.7 development by creating an account on GitHub.

github.com

 

 

 

References

[DCMTK] Source Code 빌드 방법 정리

 

[DCMTK] Source Code 빌드 방법 정리

1. 파일 다운로드 DCMTK 3.6.6 Source Code dcmtk-3.6.6-win64-support-MD-iconv-msvc-15.8 cmake-3.14.3-win64-x64.exe 2. CMake 진행 Source Code와 Build Binaries 경로 설정 Configure 클릭하여 컴파일러 버전(x64 / x86) 선택 MT 옵션들을

benstagram.tistory.com

Setup DCMTK with CMake for C++ and Visual Studio 2019 development

 

Setup DCMTK with CMake for C++ and Visual Studio 2019 development

DCMTK consists of a set of libraries and applications that implement a large part of the DICOM standard, which contains functionality to…

brandres.medium.com

 

 

 

 

 

 

반응형

C++에서 데이터를 Base Encoding/Decoding 하는 방법에 대해 알아봅니다.

 

 

 

1. base64 코드 작성

 

해당 코드는 다음 사이트를 참조하였습니다: Encoding and decoding base 64 with c++

 

Encoding and decoding base 64 with c++

This is the proposed interface for the version 2.0 of this library (as of 2020-04-29). base64_encode_pem / base64_encode_mime std::string base64_encode_pem (std::string const& s); std::string base64_encode_mime(std::string const& s); These two functions al

renenyffenegger.ch

 

//
//  base64 encoding and decoding with C++.
//  Version: 2.rc.09 (release candidate)
//

#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A

#include <string>

#if __cplusplus >= 201703L
#include <string_view>
#endif  // __cplusplus >= 201703L

std::string base64_encode     (std::string const& s, bool url = false);
std::string base64_encode_pem (std::string const& s);
std::string base64_encode_mime(std::string const& s);

std::string base64_decode(std::string const& s, bool remove_linebreaks = false);
std::string base64_encode(unsigned char const*, size_t len, bool url = false);

#if __cplusplus >= 201703L
//
// Interface with std::string_view rather than const std::string&
// Requires C++17
// Provided by Yannic Bonenberger (https://github.com/Yannic)
//
std::string base64_encode     (std::string_view s, bool url = false);
std::string base64_encode_pem (std::string_view s);
std::string base64_encode_mime(std::string_view s);

std::string base64_decode(std::string_view s, bool remove_linebreaks = false);
#endif  // __cplusplus >= 201703L

#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */

 

/*
   base64.cpp and base64.h

   base64 encoding and decoding with C++.
   More information at
     https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp

   Version: 2.rc.09 (release candidate)

   Copyright (C) 2004-2017, 2020-2022 René Nyffenegger

   This source code is provided 'as-is', without any express or implied
   warranty. In no event will the author be held liable for any damages
   arising from the use of this software.

   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely, subject to the following restrictions:

   1. The origin of this source code must not be misrepresented; you must not
      claim that you wrote the original source code. If you use this source code
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original source code.

   3. This notice may not be removed or altered from any source distribution.

   René Nyffenegger rene.nyffenegger@adp-gmbh.ch

*/

#include "base64.h"

#include <algorithm>
#include <stdexcept>

 //
 // Depending on the url parameter in base64_chars, one of
 // two sets of base64 characters needs to be chosen.
 // They differ in their last two characters.
 //
static const char* base64_chars[2] = {
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             "abcdefghijklmnopqrstuvwxyz"
             "0123456789"
             "+/",

             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             "abcdefghijklmnopqrstuvwxyz"
             "0123456789"
             "-_"};

static unsigned int pos_of_char(const unsigned char chr) {
 //
 // Return the position of chr within base64_encode()
 //

    if      (chr >= 'A' && chr <= 'Z') return chr - 'A';
    else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A')               + 1;
    else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
    else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters (
    else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_'
    else
 //
 // 2020-10-23: Throw std::exception rather than const char*
 //(Pablo Martin-Gomez, https://github.com/Bouska)
 //
    throw std::runtime_error("Input is not valid base64-encoded data.");
}

static std::string insert_linebreaks(std::string str, size_t distance) {
 //
 // Provided by https://github.com/JomaCorpFX, adapted by me.
 //
    if (!str.length()) {
        return "";
    }

    size_t pos = distance;

    while (pos < str.size()) {
        str.insert(pos, "\n");
        pos += distance + 1;
    }

    return str;
}

template <typename String, unsigned int line_length>
static std::string encode_with_line_breaks(String s) {
  return insert_linebreaks(base64_encode(s, false), line_length);
}

template <typename String>
static std::string encode_pem(String s) {
  return encode_with_line_breaks<String, 64>(s);
}

template <typename String>
static std::string encode_mime(String s) {
  return encode_with_line_breaks<String, 76>(s);
}

template <typename String>
static std::string encode(String s, bool url) {
  return base64_encode(reinterpret_cast<const unsigned char*>(s.data()), s.length(), url);
}

std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) {

    size_t len_encoded = (in_len +2) / 3 * 4;

    unsigned char trailing_char = url ? '.' : '=';

 //
 // Choose set of base64 characters. They differ
 // for the last two positions, depending on the url
 // parameter.
 // A bool (as is the parameter url) is guaranteed
 // to evaluate to either 0 or 1 in C++ therefore,
 // the correct character set is chosen by subscripting
 // base64_chars with url.
 //
    const char* base64_chars_ = base64_chars[url];

    std::string ret;
    ret.reserve(len_encoded);

    unsigned int pos = 0;

    while (pos < in_len) {
        ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);

        if (pos+1 < in_len) {
           ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);

           if (pos+2 < in_len) {
              ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
              ret.push_back(base64_chars_[  bytes_to_encode[pos + 2] & 0x3f]);
           }
           else {
              ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
              ret.push_back(trailing_char);
           }
        }
        else {

            ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
            ret.push_back(trailing_char);
            ret.push_back(trailing_char);
        }

        pos += 3;
    }


    return ret;
}

template <typename String>
static std::string decode(String const& encoded_string, bool remove_linebreaks) {
 //
 // decode(…) is templated so that it can be used with String = const std::string&
 // or std::string_view (requires at least C++17)
 //

    if (encoded_string.empty()) return std::string();

    if (remove_linebreaks) {

       std::string copy(encoded_string);

       copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end());

       return base64_decode(copy, false);
    }

    size_t length_of_string = encoded_string.length();
    size_t pos = 0;

 //
 // The approximate length (bytes) of the decoded string might be one or
 // two bytes smaller, depending on the amount of trailing equal signs
 // in the encoded string. This approximation is needed to reserve
 // enough space in the string to be returned.
 //
    size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
    std::string ret;
    ret.reserve(approx_length_of_decoded_string);

    while (pos < length_of_string) {
    //
    // Iterate over encoded input string in chunks. The size of all
    // chunks except the last one is 4 bytes.
    //
    // The last chunk might be padded with equal signs or dots
    // in order to make it 4 bytes in size as well, but this
    // is not required as per RFC 2045.
    //
    // All chunks except the last one produce three output bytes.
    //
    // The last chunk produces at least one and up to three bytes.
    //

       size_t pos_of_char_1 = pos_of_char(encoded_string.at(pos+1) );

    //
    // Emit the first output byte that is produced in each chunk:
    //
       ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char(encoded_string.at(pos+0)) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4)));

       if ( ( pos + 2 < length_of_string  )       &&  // Check for data that is not padded with equal signs (which is allowed by RFC 2045)
              encoded_string.at(pos+2) != '='     &&
              encoded_string.at(pos+2) != '.'         // accept URL-safe base 64 strings, too, so check for '.' also.
          )
       {
       //
       // Emit a chunk's second byte (which might not be produced in the last chunk).
       //
          unsigned int pos_of_char_2 = pos_of_char(encoded_string.at(pos+2) );
          ret.push_back(static_cast<std::string::value_type>( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2)));

          if ( ( pos + 3 < length_of_string )     &&
                 encoded_string.at(pos+3) != '='  &&
                 encoded_string.at(pos+3) != '.'
             )
          {
          //
          // Emit a chunk's third byte (which might not be produced in the last chunk).
          //
             ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string.at(pos+3))   ));
          }
       }

       pos += 4;
    }

    return ret;
}

std::string base64_decode(std::string const& s, bool remove_linebreaks) {
   return decode(s, remove_linebreaks);
}

std::string base64_encode(std::string const& s, bool url) {
   return encode(s, url);
}

std::string base64_encode_pem (std::string const& s) {
   return encode_pem(s);
}

std::string base64_encode_mime(std::string const& s) {
   return encode_mime(s);
}

#if __cplusplus >= 201703L
//
// Interface with std::string_view rather than const std::string&
// Requires C++17
// Provided by Yannic Bonenberger (https://github.com/Yannic)
//

std::string base64_encode(std::string_view s, bool url) {
   return encode(s, url);
}

std::string base64_encode_pem(std::string_view s) {
   return encode_pem(s);
}

std::string base64_encode_mime(std::string_view s) {
   return encode_mime(s);
}

std::string base64_decode(std::string_view s, bool remove_linebreaks) {
   return decode(s, remove_linebreaks);
}

#endif  // __cplusplus >= 201703L

 

 

 

2. 테스트

 

다음과 같이 테스트 코드를 작성합니다

 

#include <iostream>
#include "base64.h"

int main()
{
    std::string inputString = "Hello World!";
    std::string encoded = base64_encode(reinterpret_cast<const unsigned char*>(inputString.c_str()), inputString.length());
    std::cout << "encoded string: [" << encoded << "]\n";
    std::string decoded = base64_decode(encoded);
    std::cout << "decoded string: [" << decoded << "]\n";
}

 

콘솔에서 확인하면 다음과 같이 정상적으로 출력됩니다.

 

 

 

 

 

 

반응형

 

C#의 GZipStream으로 압축된 String 데이터를 C++ 프로그램에서 다룰 일이 생겼습니다. 이를 위한 라이브러리 검토 중 POCO C++를 사용해 테스트를 진행해보도록 하겠습니다.

 

 

 

1. POCO C++ 다운로드

 

vcpkg를 사용해 라이브러리를 다운로드합니다. vcpkg 설치는 다음 글을 참조해 설치해 주시기 바랍니다: C++ 라이브러리를 위한 vcpkg 설치 방법

 

C++ 라이브러리를 위한 vcpkg 설치 방법

Window 환경에서 C++ 라이브러리를 위한 vcpkg를 설치하는 방법에 대해 알아봅니다. vcpkg 설치. 가장 쉬운 방법은 공식 홈페이지의 안내를 따르는 방법입니다. git을 미리 설치했다면 두줄의 명령줄로

smoh.kr

 

vcpkg가 설치된 폴더로 이동해 다음 명령어로 POCO C++를 다운로드합니다.

 

.\vcpkg install POCO:x64-windows

 

 

잠시 기다리면 다운로드와 빌드가 완료되고 라이브러리를 확인할 수 있습니다.

 

 

 

 

2. 프로젝트 생성

 

간단한 C++ 콘솔 프로젝트를 생성합니다. 이후 다운로드한 라이브러리를 import 합니다.

 

 

 

이제 "Hello World"를 gzip 압축 및 압축 해제하는 코드를 작성합니다.

 

 

 

3. 코드 작성

 

다음과 같이 코드를 작성합니다.

 

#include <iostream>
#include <sstream>
#include <Poco/InflatingStream.h>
#include <Poco/DeflatingStream.h>
#include <Poco/StreamCopier.h>

int main()
{
    std::ostringstream stream1;
    Poco::DeflatingOutputStream
        gzipper(stream1, Poco::DeflatingStreamBuf::STREAM_GZIP);
    gzipper << "Hello World!";
    gzipper.close();
    std::string zipped_string = stream1.str();
    std::cout << "zipped_string: [" << zipped_string << "]\n";

    std::ostringstream stream2;
    Poco::InflatingOutputStream
        gunzipper(stream2, Poco::InflatingStreamBuf::STREAM_GZIP);
    gunzipper << zipped_string;
    gunzipper.close();
    std::string unzipped_string = stream2.str();
    std::cout << "unzipped_string back: [" << unzipped_string << "]\n";
}

 

"Hello World!"를 GZIP 압축 및 압축 해제하는 코드입니다. 콘솔로 실행시키면 다음과 같이 정상 동작하는 것을 확인할 수 있습니다.

 

 

 

 

 

 

반응형

 

Window 환경에서 C++ 라이브러리를 위한 vcpkg를 설치하는 방법에 대해 알아봅니다.

 

 

 

vcpkg 설치.

 

가장 쉬운 방법은 공식 홈페이지의 안내를 따르는 방법입니다. git을 미리 설치했다면 두줄의 명령줄로 설치를 완료할 수 있습니다: Get started with vcpkg

 

Get started with vcpkg

Installing vcpkg is a two-step process: first, clone the repo, then run the bootstrapping script to produce the vcpkg binary. The repo can be cloned anywhere, and will include the vcpkg binary after bootstrapping as well as any libraries that are installed

vcpkg.io

 

공식 홈페이지에서는 전역으로 설치하는 경우 C:\src\vcpkg 또는 C:\dev\vcpkg와 같은 짧은 설치 경로를 권장하고 있습니다.

 

터미널(혹은 명령 창)을 열어 원하는 경로로 이동 한 뒤 다음 명령어를 실행합니다.

 

$git clone https://github.com/Microsoft/vcpkg.git

 

잠시 기다리면 다음과 같이 다운로드가 완료됩니다.

 

 

이어서 다음 명령어를 실행해 줍니다.

 

 

.\vcpkg\bootstrap-vcpkg.bat

 

다음 화면과 같이 정상적으로 처리되는 것을 확인할 수 있습니다.

 

 

만약 VisualStudio에서 vcpkg를 사용하고자 한다면 추가로 다음 명령어를 수행해야 합니다.

 

.\vcpkg\vcpkg integrate install

 

관리자 권한이 요구되며 다음과 같이 완료됩니다.

 

 

 

 

라이브러리 설치

 

가장 대표적인 C++ 라이브러리인 boost를 vcpkg를 사용해 설치해 봅시다. 다음 명령어를 입력해 boost(x64)를 설치합니다. 

** boost는 매우 방대한 라이브러리입니다. 상당히 오랜 시간이 소요되니 테스트 용도라면 다른 라이브러리로 테스트하셔도 됩니다.

 

.\vcpkg\vcpkg install boost:x64-windows

 

위와 같이 실행하면 64비트로 빌드된 boost 관련 라이브러리를 모두 다운로드하게 됩니다.

 

 

이제 기다리면 리스트업 된 모든 라이브러리를 다운로드하게 되고 명령어를 통해 다운로드한 라이브러리를 확인할 수 있습니다.

 

 

.\vcpkg\vcpkg list

 

 

라이브러리 파일은 다음 경로에서 확인할 수 있습니다.

 

 

정상적으로 라이브러리가 다운로드된 것을 확인할 수 있습니다.

 

 

 

 

 

반응형

 

 

mfc100ud.lib 파일을 열 수 없습니다 문제를 해결하는 방법에 대해 알아봅니다.

 

 

 

1. 현상

 

 

잘 빌드되던 프로젝트를 오래간만에 빌드했더니 "mfc100ud.lib 파일을 열 수 없습니다." 에러가 발생합니다.

 

 

 

2. 원인 

 

암만 생각해도 소스를 변경한 기억이 없었고 뭐가 문제인지 곰곰이 생각해보던 도중 VisualStudio 2022 Pre 버전을 설치했다 지운적이 있었음이 기억났습니다.

 

환경변수를 확인해본 결과 atlmfc 경로가 환경변수에서 빠져있었음을 확인할 수 있었습니다.

 

 

 

3. 수정

 

환경변수에 mfc100 경로를 추가해 줍니다.

 

 

경로 확인 결과 해당 파일이 "C:\Program Files (x86)\Microsoft Visual Studio 10.0"아래에 있음을 확인할 수 있었습니다.

 

"C:\Program Files (x86)\Microsoft Visual Studio 10.0"를 환경 변수에 추가한 뒤에 정상적으로 빌드됨을 확인하였습니다.

 

 

 

 

 

반응형

 

Fatal error C1083 포함 파일을 열 수 없습니다. 'ctype.h': No such file or directory / Cannot open include file: 'ctype.h': No such file or directory 에러가 발생했을 때 해결 방법에 대해 알아봅니다.

 

 

 

1. 현상

 

최근 C++ 프로젝트에서 curl을 사용할 일이 생겨 소스코드를 받아 빌드를 시도했습니다.

 

한 번에 성공하면 좋았으나 위와 같은 에러가 발생했습니다.

 

 

 

2. 해결

 

에러 로그를 가만 보고 있자니 왜인지 "windows kit 8.1"이 눈에 들어옵니다. 프로젝트 -> 속성 -> 일반으로 이동해 Windows SDK 버전을 변경해 줍시다.

 

 

대상 프로젝트는 VisualStudio 2017에서 사용하므로 SDK 버전을 10.0.17134.0으로 변경해줬습니다.

 

이제 다시 빌드하면 정상적으로 빌드가 되는 것을 확인할 수 있습니다.

 

 

 

 

 

 

 

반응형

 

 

 

 

1. 현상

 

컴파일에서 문제는 없지만 런타임에서 AWS SDK를 사용하는 도중에 aws-cpp-sdk-core.dll에서 Assertion failed가 발생합니다. 

 

 

위와 같은 화면과 함께 실행이 중단되며 IDE에 별도의 오류는 찍혀있지 않습니다. 해당 오류는 Aws::Auth::AWSCredentials, Aws::S3::S3Client를 생성할 때 발생했습니다.

 

 

 

2. 원인 및 수정

 

aws-sdk-cpp GitHub의 Issue에서 원인과 해결방법을 찾을 수 있었습니다: Assertion failed: (s_HttpClientFactory), function CreateHttpRequest

 

Assertion failed: (s_HttpClientFactory), function CreateHttpRequest · Issue #778 · aws/aws-sdk-cpp

I use Cognito libs in my app and use blocking calls from my custom threads. Application is crashing when I it is closed before active request has completed. Assertion failed: (s_HttpClientFactory),...

github.com

 

Bu11etmagnet의 멘션처럼 cpp에서 aws-sdk를 사용하기 위해서는 먼저 InitAPI를 호출해야만 합니다. InitAPI를 호출하지 않고 aws-sdk를 사용하려고 했기 때문에 위와 같은 오류가 발생했습니다. aws-sdk 사용에 앞서 다음 코드를 수행해 주시면 됩니다.

 

Aws::SDKOptions awsOptions;
// ...
Aws::InitAPI(awsOptions);
// ...
Aws::ShutdownAPI(awsOptions);

 

awsOption를 먼저 선언 후 aws-sdk를 사용하기 전에 IniAPI를 호출합니다. 모든 API 사용이 끝난 뒤 더 이상 사용하지 않을 땐 ShutdownAPI를 호출해 마무리하면 됩니다.

 

 

 

 

 

반응형

 

1. 현상

 

한 솔루션에서 S3 지원 업그레이드 소스를 작성하고 다른 솔루션에 적용하기 위해 소스코드를 그대로 가져와 컴파일하는 도중에 Aws::MakeShared에서 "std::shared_ptr<Aws::FStream>"에서 "std::shared_ptr<Aws::IOStream>"으로의 사용자 정의 변환이 적절하지 않습니다. 라는 이상한 에러가 발생합니다.

 

std::shared_ptr<Aws::IOStream> input_data = Aws::MakeShared<Aws::FStream>("SampleAllocationTag", objectName.c_str(), std::ios_base::in | std::ios_base::binary);

 

 

 

 

2. 원인 및 수정.

 

소스코드를 제대로 보지 않고 필요한 헤더만 찾아서 코딩해 발생한 에러였습니다.

 

github.com/aws/aws-sdk-cpp/issues/1168

 

Compilation errors for file upload via S3Client PutObject in C++ on Mac · Issue #1168 · aws/aws-sdk-cpp

What platform/OS are you using? Darwin 17.7.0 Darwin Kernel Version 17.7.0: Wed Apr 24 21:17:24 PDT 2019; root:xnu-4570.71.45~1/RELEASE_X86_64 x86_64 Which version of the SDK? master branch of aws-...

github.com

 

위의 이슈를 제기한 분도 저랑 동일한 실수를 저질렀나 봅니다. 다시 한번 AWS의 예시 코드를 확인했습니다. 

 

Upload an Object

 

Operations on Objects - AWS SDK for C++

Operations on Objects An Amazon S3 object represents a file, which is a collection of data. Every object must reside within a bucket. These code snippets assume that you understand the material in Getting Started Using the AWS SDK for C++ and have configur

docs.aws.amazon.com

 

#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/PutObjectRequest.h>
#include <awsdoc/s3/s3_examples.h>

bool AwsDoc::S3::PutObject(const Aws::String& bucketName, 
    const Aws::String& objectName,
    const Aws::String& region)
{
    // Verify that the file exists.
    struct stat buffer;

    if (stat(objectName.c_str(), &buffer) == -1)
    {
        std::cout << "Error: PutObject: File '" <<
            objectName << "' does not exist." << std::endl;

        return false;
    }

    Aws::Client::ClientConfiguration config;

    if (!region.empty())
    {
        config.region = region;
    }

    Aws::S3::S3Client s3_client(config);
    
    Aws::S3::Model::PutObjectRequest request;
    request.SetBucket(bucketName);
    request.SetKey(objectName);

    std::shared_ptr<Aws::IOStream> input_data = 
        Aws::MakeShared<Aws::FStream>("SampleAllocationTag", 
            objectName.c_str(), 
            std::ios_base::in | std::ios_base::binary);

    request.SetBody(input_data);

    Aws::S3::Model::PutObjectOutcome outcome = 
        s3_client.PutObject(request);

    if (outcome.IsSuccess()) {

        std::cout << "Added object '" << objectName << "' to bucket '"
            << bucketName << "'.";
        return true;
    }
    else 
    {
        std::cout << "Error: PutObject: " << 
            outcome.GetError().GetMessage() << std::endl;
       
        return false;
    }
}

 

코드만 보지말고 위의 include를 잘 보면 "include <fstream>"이 존재합니다. fstream을 include 해주면 문제없이 잘 컴파일됩니다.

 

 

 

 

 

반응형

 

이번에 C++로 AWS SDK를 사용할 일이 생겼습니다. 매우 오래된 구식 프로그램이라 AWS SDK를 지원하지 않아 VC100에서 먼저 업그레이드해야 할 상황이 닥쳤습니다. 한참을 끙끙대며 업그레이드하고 나니 C#과는 달리 C++에서는 직접 소스를 빌드해 SDK를 사용해야 한답니다. C#처럼 Nuget을 이용할 수 있을 줄 알았는데... 아무튼 이번 글에서는 C++에서 AWS SDK를 사용할 수 있는 방법에 대해 알아보도록 하겠습니다. 

 

Nuget 패키지 관리자로 검색해보면 AWSSDKCPP라는 이름의 패키지가 존재하긴 합니다. 하지만 글 쓸 당시 aws-sdk-cpp GitHub에서는 1.8 버전이 릴리즈 되었지만 Nuget에서는 1.6 버전이 최신이었습니다. 따라서 이 글에선 CMake를 이용해 C++용 AWS SDK를 직접 빌드해 사용하는 방법에 대해 알아보도록 하겠습니다.

 

 

 

0. 요구사항.

 

C++용 AWS SDK를 사용하기 위한 요구사항은 다음과 같습니다.

  • VisualStudio 2015 또는 그 이상.
  • GNU Compiler Collection(GCC) 4.9 또는 그 이상.
  • CLang 3.3 또는 그 이상
  • 4GB의 메모리(큰 규모의 클라이언트 구축을 위해서 필요합니다. 메모리 부족으로 인해 SDK 빌드가 실패할 수도 있습니다.)

사전 요구사항을 확인한 후 빌드를 준비합니다.

 

 

 

1. CMake 준비

 

프로젝트 빌드를 위해 CMake를 미리 설치해야 합니다. CMake 페이지로 이동해 빌드할 플랫폼에 맞는 CMake를 설치해 준비합니다.

 

 

 

 

2. 프로젝트 코드 다운로드.

 

aws-sdk-cpp GitHub 페이지로 이동해 소스코드를 다운로드합니다.

 

 

Github 페이지 우측 상단에 Zip으로 다운로드하기가 있습니다. 원하는 버전의 전체 소스코드를 다운로드하여 압축을 풀어 주세요. 전 1.8.118 버전을 다운로드하여 D:\Dev\aws-sdk-cpp-1.8.118 폴더에 압축을 풀어주었습니다.

 

 

 

3. 솔루션 및 프로젝트 생성

 

이제 CMake를 실행시켜 프로젝트를 만들어줍니다. BrowseSource 버튼을 클릭해 코드가 위치한 폴더를 선택합니다. BrowseBuild 버튼을 클릭해 CMake 결과물이 위치할 폴더를 선택합니다. 

 

 

전 위와 같이 설정해 줬습니다. 폴더를 설정해 준 뒤 Configure 버튼을 클릭합니다. CMake가 선택한 Source폴더를 확인해 자동으로 설정을 구성합니다. Configure 버튼을 클릭하면 생성될 프로젝트를 설정할 수 있는 창이 보입니다. 원하는 대로 선택해 줍니다.

 

 

원하는 대로 설정 후 Finish 버튼을 클릭하면 구성을 시작합니다. 아래의 텍스트 박스에 진행상황에 대한 로그가 같이 남습니다. 느긋이 기다려 주도록 합니다.

 

 

작업이 완료되면 가운데 구성 설정 목록이 나타납니다. 또한 앞서 설정한 빌드 폴더로 가보면 프로젝트 생성에 필요한 파일이 복사되어 있는 것을 확인할 수 있습니다.

 

 

원하는 설정이 있다면 여기서 변경해 주시면 됩니다. 일단 CMake가 생성한 기본값을 갖고 솔루션과 프로젝트를 생성해 보도록 하겠습니다. 설정이 끝나면 Generate 버튼을 클릭해 주세요.

 

잠시 기다리면 "Generating done" 메시지와 함께 솔루션 및 프로젝트 생성이 종료됩니다. 이후 앞서 설정한 binaries 폴더인 Build 폴더에 들어가면 C++ 솔루션이 생성되어 있습니다. 이제 솔루션으로 프로젝트를 빌드 해 AWS SDK를 사용할 수 있습니다.

 

 

 

 

 

 

반응형

Error: LNK1117 'VERSION: 1.0.0.0' 옵션에 구문 오류가 있습니다. 와 같은 에러가 발생한 경우 해결 방법에 대해 알아봅니다.

 

 

 

1. 현상.

 

인수인계받은 프로젝트를 빌드하려고 보니 디버그 빌드는 정상적으로 되었으나 릴리즈 빌드에서 "Error: LNK1117 'VERSION: 1.0.0.0' 옵션에 구문 오류가 있습니다."가 발생했습니다. 

 

 

 

2. 원인.

 

오래된 프로젝트에서 프로젝트 속성의 버전에 1.0.0.0이라는 값을 고정시켜 두어 발생했습니다.

 

 

 

3. 해결

 

해당 프로젝트 우클릭 -> 속성 -> 구성 속성 -> 링커 -> 일반 -> 버전의 값을 삭제 후 빌드합니다.

 

 

 

 

 

 

반응형

'Programming > C++' 카테고리의 다른 글

[AWSSDKCPP] Aws::MakeShared 에러  (0) 2021.01.28
[C++] C++에서 AWS SDK 직접 빌드해 사용하기.  (0) 2021.01.05
[C++] Convert CStirng to const char*  (0) 2020.05.20
[C++] DCMTK - Generate UID  (0) 2018.05.11
[C++] CString to const char*  (0) 2018.05.11

+ Recent posts