AWS SDK for C++

repository·main·Indexed 24 days ago

https://github.com/aws/aws-sdk-cpp

A modern C++ (C++11 or later) interface for interacting with Amazon Web Services, designed for high performance and platform portability across Windows, OSX, Linux, and mobile. The SDK provides core utilities for string handling, hashing, cryptography, and JSON/XML parsing, and supports custom HTTP clients, retry strategies, and bandwidth rate limiting via the ClientConfiguration struct.

Tokens
17.8K
Snippets
29
Records
95
Agent score
81%

What's inside aws-sdk-cpp

  1. Efficient service calls using non-STL overloads

    main

    To minimize temporary allocations and memory overhead when making service calls, the SDK provides several non-STL overloads for Init and Set functions. Instead of constructing std::string or std::vector objects, use these variants:

    • Strings: Use overloads that take const char* or (optionally) a const char* with an explicit length.
    • Containers (Map/Vector): Use add variants that take a single entry instead of passing a whole container.
    • Binary Data: Use overloads that take a pointer and a length value.
  2. Handle errors using Outcome objects

    main

    The AWS SDK for C++ does not use exceptions for service errors. Instead, every service client method returns an outcome object (e.g., CreateTableOutcome). You should check the success of the operation using .IsSuccess() and, if it fails, inspect the error using .GetError().

    CreateTableOutcome createTableOutcome = dynamoDbClient->CreateTable(createTableRequest);
    if (createTableOutcome.IsSuccess())
    {
       // Handle success
    }
    else if(createTableOutcome.GetError().GetErrorType() == DynamoDBErrors::RESOURCE_IN_USE)
    {
       // Handle specific error type
    }
  3. Error handling pattern in AWS SDK for C++

    main
    The SDK prohibits the use of C++ exceptions. Instead, use the Outcome pattern to return data. This pattern allows you to return a successful result or an error code/object within a single return type, ensuring predictable control flow without the overhead or instability of exception handling.
  4. Memory management and RAII guidelines

    main

    To ensure stability with custom memory managers, follow these memory management rules:

    • Use RAII: Rely on Resource Acquisition Is Initialization to manage object lifetimes.
    • Avoid non-trivial statics: Using non-trivial static objects can cause custom memory managers to crash unpredictably.
    • Controlled allocation: Aws::New and Aws::Delete should only be used within constructors and destructors.
    • Rule of 5: Always implement or explicitly delete the copy/move constructors and assignment operators to manage resources correctly.
    • Use nullptr: Always use nullptr instead of the NULL macro.
  5. Customize Retry Strategy and Executor

    main

    The SDK provides default behaviors for retries and asynchronous execution, but these can be customized by implementing specific interfaces:

    • Retry Strategy: The default is exponential backoff. To change this, implement a subclass of RetryStrategy and assign it to the retryStrategy field.
    • Executor: By default, the SDK creates and detaches a new thread for each async call. To use a different model, such as a thread pool, implement a subclass of Executor and assign it to the executor field.
  6. How the Default Credential Provider Chain works

    main

    The AWS SDK for C++ uses a default credential provider chain to automatically locate credentials. When no specific credentials are provided to a client, the SDK searches in the following order:

    1. Environment Variables: Checks for standard AWS credential environment variables.
    2. Shared Credentials File: Checks $HOME/.aws/credentials for a profile and credentials.
    3. Web Identity/Identity Providers: Contacts trusted providers (Cognito, LWA, Facebook, Google) using information found in environment variables (AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_SESSION_NAME) or a profile in $HOME/.aws/credentials.
    4. External Profile Methods: Checks $HOME/.aws/config for external methods used to generate or look up credentials.
    5. ECS Task Roles: If AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set, it contacts the ECS TaskRoleCredentialsProvider service.
    6. EC2 Instance Metadata: If AWS_EC2_METADATA_DISABLED is NOT set to true, it contacts the EC2MetadataInstanceProfileCredentialsProvider service.

    To simplify development, ensure your credentials are placed in one of these standard locations.

  7. How USE_AWS_MEMORY_MANAGEMENT affects STL types

    main

    The SDK uses type aliasing to manage how STL containers (like Vector, String, Map) behave based on the USE_AWS_MEMORY_MANAGEMENT compile-time constant. This ensures that the SDK's internal use of STL is compatible with your custom memory manager.

    • If USE_AWS_MEMORY_MANAGEMENT is ON: Aws::* types (e.g., Aws::Vector<T>) resolve to STL types using a custom Aws::Allocator<T> that connects to the AWS memory system.
    • If USE_AWS_MEMORY_MANAGEMENT is OFF: Aws::* types resolve to standard std::* types using default allocators.

    This mechanism allows the SDK to use custom allocators internally while maintaining a consistent interface.

  8. Understand the S3EncryptionClient major version lifecycle

    main
    The S3 Encryption Client manages major version updates by using separately named classes. When a new major version is released, you should transition to the new class name to access new features, security patches, and updated API support. For example, moving from S3EncryptionClient to S3EncryptionClientV2 represents a major version upgrade.
  9. Disable checksums for optional-checksum APIs

    main

    For APIs where checksums are not required (e.g., PutObject), the SDK defaults to sending a CRC64-NVME checksum. If you need to send no checksum at all (for compatibility with 3rd party S3 services that do not support the new default), set requestChecksumCalculation to Client::RequestChecksumCalculation::WHEN_REQUIRED in your S3ClientConfiguration.

    Warning: Disabling checksums means there are no object integrity checks, and data could be corrupted during transmission.

    #include <aws/core/Aws.h>
    #include <aws/s3/S3Client.h>
    #include <aws/s3/model/PutObjectRequest.h>
    
    using namespace Aws;
    using namespace Aws::S3;
    using namespace Aws::S3::Model;
    
    namespace {
      constexpr const char* LOG_TAG = "TestApplication";
      constexpr const char* BUCKET_NAME = "BUCKET_NAME";
      constexpr const char* KEY = "OBJECT_KEY";
    }
    
    auto main() -> int {
      SDKOptions options;
      options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Debug;
      InitAPI(options);
      {
        S3ClientConfiguration configuration;
        configuration.checksumConfig.requestChecksumCalculation = 
        Client::RequestChecksumCalculation::WHEN_REQUIRED;
        S3Client client{configuration};
        auto request = PutObjectRequest().WithBucket(BUCKET_NAME).WithKey(KEY);
        std::shared_ptr<IOStream> body = Aws::MakeShared<StringStream>(LOG_TAG, 
          "sample text stream");
        request.SetBody(body);
        const auto response = client.PutObject(request);
        assert(response.IsSuccess());
      }
      ShutdownAPI(options);
      return 0;
    }
  10. Memory management best practices for SDK developers

    main

    When writing code that interacts with or extends the SDK, follow these memory management rules to ensure compatibility with the SDK's allocation system:

    TaskRecommended Method
    Single object allocationAws::New<T>() and Aws::Delete<T>()
    Array allocationAws::NewArray<T>() and Aws::DeleteArray<T>()
    Shared pointer creationAws::MakeShared<T>(...)
    Unique pointer (single)Aws::UniquePtr<T> created via Aws::MakeUnique<T>(...)
    Unique pointer (array)Aws::UniqueArray<T> created via Aws::MakeUniqueArray<T>(...)
    STL ContainersUse Aws::* typedefs (e.g., Aws::Map<K, V>) instead of direct std::* containers

    Note on Shared Pointers: For any external pointer passed into and managed by the SDK, use std::shared_ptr. You must initialize the shared pointer with a destruction policy that matches how the object was allocated. If the SDK is not expected to clean up the pointer, you may use a raw pointer.

  11. Cross-compile for Android

    main

    When building for Android, use the following CMake variables to configure the environment:

    • NDK_DIR: Path to the Android NDK (checks ANDROID_NDK env var if not set).
    • ANDROID_ABI: Target ABI. Supported: arm64, armeabi-v7a (default), x86_64, x86, mips64, mips.
    • ANDROID_STL: C++ standard library. Options: libc++_shared (default), libc++_static, gnustl_shared, gnustl_static. Note: libc++ is recommended; gnustl has performance issues and is deprecated in NDK 18+.
    • ANDROID_NATIVE_API_LEVEL: Target API level. If using libc++, this must be at least 21.
    • ANDROID_TOOLCHAIN: Compiler to use. Default is clang (recommended).
    • ANDROID_BUILD_CURL, ANDROID_BUILD_OPENSSL, ANDROID_BUILD_ZLIB: Boolean flags to include these dependencies in the Android build (all default to ON).