C/C++

ESP32 HTTP POST with JSON body using ArduinoJson

This example parses a HTTP POST request body using ArduinoJson. I recommend using my HumanESPHTTP library as simple server library based on the ESP-IDF HTTP server.

constexpr size_t JsonParseBufferSize = 2048;
typedef ArduinoJson::StaticJsonDocument JsonParseBuffer;

/**
 * This buffer is used to parse /api/configure events
*/
static JsonParseBuffer document;

static const httpd_uri_t configureHandler = {
    .uri       = "/api/configure",
    .method    = HTTP_POST,
    .handler   = [](httpd_req_t *req) {
        // Receive POST body data into a new buffer
        char* jsonBody = (char*)malloc(req->content_len + 1);
        jsonBody[req->content_len] = '\0'; // NUL terminate [just in case]
        if(jsonBody == nullptr) {
            return SendStatusError(req, "Failed to allocate memory for JSON body");
        }
        int err = httpd_req_recv(req, jsonBody, req->content_len);
        if(err != req->content_len) {
            free(jsonBody);
            return SendStatusError(req, "Failed to read request body");
        }
        // Parse the body as JSON
        deserializeJson(document, jsonBody, req->content_len);
        // TODO: Do something with [document]
        // Cleanup
        free(jsonBody);
        return SendStatusOK(req);
    }
};

which uses the following utility functions:

esp_err_t SendStatusError(httpd_req_t *request, const char* description) {
    httpd_resp_set_type(request, "application/json");
    httpd_resp_send_chunk(request, "{\"status\":\"error\", \"error\": \"", HTTPD_RESP_USE_STRLEN);
    // NOTE: We silently assume that description does not have any special characters
    httpd_resp_send_chunk(request, description, HTTPD_RESP_USE_STRLEN);
    httpd_resp_send_chunk(request, "\"}", HTTPD_RESP_USE_STRLEN);
    httpd_resp_send_chunk(request, nullptr, 0); // Finished
    return ESP_OK;
}

esp_err_t SendStatusOK(httpd_req_t *request) {
    httpd_resp_set_type(request, "application/json");
    httpd_resp_sendstr(request, "{\"status\":\"ok\"}");
    return ESP_OK;
}

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32

How to fix ESP32 rmt: rmt_transmit(466): loop count is not supported

If you encounter

rmt: rmt_transmit(466): loop count is not supported

on the ESP32, this is because you have used a rmt_transmit_config_t with explicitly set loop_count.

rmt_transmit_config_t cfg = {
  .loop_count = 1,
  .flags = {
      .eot_level = 0,
   }
};
ESP_ERROR_CHECK(rmt_transmit(/* ... */, &cfg));

but your IC (e.g. ESP32-D0WD-V3)  does not support hardware loop mode.

Fixing this is easy: Just comment out the .loop_count line:

rmt_transmit_config_t cfg = {
  //.loop_count = 1, // DISABLED as chip does not support it
  .flags = {
      .eot_level = 0,
   }
};
ESP_ERROR_CHECK(rmt_transmit(/* ... */, &cfg));

Note that if you leave .loop_count at its default, it will always act as if .loop_count = 1.

Posted by Uli Köhler in C/C++, ESP8266/ESP32

ESP-IDF minimal Wifi client hello world example using PlatformIO

This basic example showcases how to use PlatformIO with ESP-IDF only (no Arduino) to connect to Wifi in station mode and print Hello world in a loop. It is based on the basic Hello World example from PlatformIO ESP32 with ESP-IDF minimal C++ example:

#include <cstdio>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

#include <esp_wifi.h>
#include <esp_log.h>
#include <nvs_flash.h>
#include <esp_netif.h>
#include <esp_event.h>


extern "C" {
    void app_main(void);
}


static void NetworkEventHandler(void* arg, esp_event_base_t event_base,
                          int32_t event_id, void* event_data) {
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        ESP_LOGI("wifi", "Retrying to connect to Wifi...");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI("wifi", "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
    }
}

void InitNVS() {
    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
}

void InitWifi() {

    // Initialize TCP/IP network interface (required for Wi-Fi)
    ESP_ERROR_CHECK(esp_netif_init());

    // Initialize the event loop
    ESP_ERROR_CHECK(esp_event_loop_create_default());    
    esp_netif_create_default_wifi_sta();

    // Initialize Wi-Fi
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    // Set Wi-Fi to station mode
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

    // Configure the Wi-Fi connection
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "MyWifi",
            .password = "mypassword"
        }
    };
    // Register event handler
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &NetworkEventHandler,
                                                        NULL,
                                                        NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &NetworkEventHandler,
                                                        NULL,
                                                        NULL));

    // Set Wi-Fi configuration and start Wi-Fi
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
}

void app_main() {
    InitNVS();
    InitWifi();

    while(true) {
        printf("Hello PlatformIO!\n");
        // Wait for one second
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = espidf
monitor_speed = 115200

All sdkconfig settings have been left at their respective defaults.

Posted by Uli Köhler in C/C++, ESP8266/ESP32, PlatformIO

How to fix ESP-IDF error: cannot convert ‘esp_interface_t’ to ‘wifi_interface_t’

Problem:

While trying to  compile your ESP-IDF app using code such as

ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));

you see an error message such as

src/main.cpp:76:41: error: cannot convert 'esp_interface_t' to 'wifi_interface_t'
   76 |     ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
      |                                         ^~~~~~~~~~~~~~~
      |                                         |
      |                                         esp_interface_t

Solution:

Instead of ESP_IF_WIFI_STA, use WIFI_IF_STA (which has the correct type):

ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32

PlatformIO ESP32 with ESP-IDF minimal C++ example

By default, when you initialize a PlatformIO ESP-IDF project, it will generate main.c – not a C++ but a pure C file

This minimal example instead uses main.cpp (you can just rename your main.c – see How to use C++ main.cpp with PlatformIO on ESP32 / esp-idf for a detailed list of steps to do).

#include <cstdio>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

extern "C" {
    void app_main(void);
}

void app_main() {
    while(true) {
        printf("Hello PlatformIO!\n");
        // Wait for one second
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32, PlatformIO

How to use C++ main.cpp with PlatformIO on ESP32 / esp-idf

When you are using PlatformIO to compile your firmware, it is easily possible to use a C++ main.cpp instead of the pure C main.c by just renaming main.c to main.cpp

However, you also need to properly declary app_main(). After the #include section of your main.cpp (or at the top of the file if you don’t have an #include section yet), add this code:

extern "C" {
    void app_main(void);
}

This will tell the compiler that app_main() is a C function, not a C++ function.

Full main.cpp example

#include <cstdio>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

extern "C" {
    void app_main(void);
}

void app_main() {
    while(true) {
        printf("Hello PlatformIO!\n");
        // Wait for one second
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32, PlatformIO

How to generate inverted pulses using the ESP32 RMT module (Arduino & PlatformIO)

In our previous post ESP32 RMT pulse generation minimal example using Arduino & PlatformIO using the RMT peripheral. The pulses have a steady state (off state) of 0V and a pulse voltage of 3.3V.

If we want to generate inverted pulses, we have to invert the level entries in the pulseRMT array:

static const rmt_item32_t pulseRMT[] = {
    {{{
      /*pulse duration=*/100, /*pulse level*/0,
      // After pulse, output 1
      0, 1
    }}},
};

and additionally configure the RMT output when the pulse is finished using

config.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;
config.tx_config.idle_output_en = true;

This is how the pulse looks like:

Full example:

#include <Arduino.h>
#include <esp_log.h>
#include <driver/rmt.h>

// Output pulse train on D14
constexpr gpio_num_t rmtPin = GPIO_NUM_14;
constexpr rmt_channel_t RMT_TX_CHANNEL = RMT_CHANNEL_0;

static const rmt_item32_t pulseRMT[] = {
    {{{
      /*pulse duration=*/100, /*pulse level*/0,
      // After pulse, output 1
      0, 1
    }}},
};

void setup() {
  Serial.begin(115200);

  rmt_config_t config = RMT_DEFAULT_CONFIG_TX(rmtPin, RMT_TX_CHANNEL);
  config.clk_div = 80; // input clock 80 MHz => output clk 1 MHz
  config.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;
  config.tx_config.idle_output_en = true;

  ESP_ERROR_CHECK(rmt_config(&config));
  ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));

}

void loop() {
  ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, pulseRMT, sizeof(pulseRMT) / sizeof(rmt_item32_t), true));
  delay(10);
}

 

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200

 

Posted by Uli Köhler in Arduino, C/C++, ESP8266/ESP32, PlatformIO

ESP32 HTTP float query parser with range check example using HumanESPHTTP

Example for HumanESPHTTP

static const httpd_uri_t setPowerHandler = {
    .uri       = "/api/set-power",
    .method    = HTTP_GET,
    .handler   = [](httpd_req_t *request) {
        QueryURLParser parser(request);
        if(parser.HasParameter("power")) {
            std::string power = parser.GetParameter("power");
            // Parse power as float
            float powerFloat;
            try {
              powerFloat = std::stof(power);
            } catch (const std::invalid_argument& e) {
              httpd_resp_set_status(request, "400 Bad Request");
              httpd_resp_set_type(request, "text/plain");
              httpd_resp_sendstr(request, "Error: Invalid argument for power parameter (not a float)!");
              return ESP_OK;
            }
            // Check range
            if(powerFloat < 0.0 || powerFloat > 1.0) {
              httpd_resp_set_status(request, "400 Bad Request");
              httpd_resp_set_type(request, "text/plain");
              httpd_resp_sendstr(request, "Error: Invalid argument for power parameter (not in range 0.0 ... 1.0)!");
              return ESP_OK;
            }
            // TODO: Your code goes here
            // Example code: send back power
            httpd_resp_send_chunk(request, "Power is: ", HTTPD_RESP_USE_STRLEN);
            httpd_resp_send_chunk(request, std::to_string(powerFloat).c_str(), HTTPD_RESP_USE_STRLEN);
            httpd_resp_send_chunk(request, nullptr, 0); // Finished
        } else {
            httpd_resp_set_type(request, "text/plain");
              httpd_resp_set_status(request, "400 Bad Request");
            httpd_resp_sendstr(request, "No 'power' query parameter found!");
        }
        return ESP_OK;
    }
};

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32

ESP32 RMT pulse generation minimal example using Arduino & PlatformIO

The following example will generate 100us pulses every 10ms. The pulses are generated using the RMT peripheral.

#include <Arduino.h>
#include <esp_log.h>
#include <driver/rmt.h>

// Output pulse train on D14
constexpr gpio_num_t rmtPin = GPIO_NUM_14;
constexpr rmt_channel_t RMT_TX_CHANNEL = RMT_CHANNEL_0;


static const rmt_item32_t pulseRMT[] = {
    {{{
      /*pulse duration=*/100, /*pulse level*/1,
      // After pulse, output 0
      0, 0
    }}},
};


void setup() {
  Serial.begin(115200);

  rmt_config_t config = RMT_DEFAULT_CONFIG_TX(rmtPin, RMT_TX_CHANNEL);
  config.clk_div = 80; // input clock 80 MHz => output clk 1 MHz

  ESP_ERROR_CHECK(rmt_config(&config));
  ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));

}

void loop() {
  ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, pulseRMT, sizeof(pulseRMT) / sizeof(rmt_item32_t), true));
  delay(10);
}

 

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200

 

Posted by Uli Köhler in Arduino, C/C++, ESP8266/ESP32, PlatformIO

How to fix Arduino / PlatformIO undefined reference to `loop()’

Problem:

While trying to compile your Arduino or PlatformIO project, you see an error message such as
/home/uli/.platformio/packages/[email protected]+2021r2-patch5/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/esp32dev/libFrameworkArduino.a(main.cpp.o):(.literal._Z8loopTaskPv+0x8): undefined reference to `loop()'

Solution:

You have not declared a loop() function in your source code. Open main.cpp or your .ino source code file and start with the following (empty) loop() function which does nothing:
void loop() {
    // Nothing to do here since HTTPServer
    // is running in a separate thread
    delay(1000);
}
After you’ve added any void loop() { /* ... */} function to your sourcecode try to build/upload again and the error message should have disappeared.
If you want, you can also add code such as to print a message to the serial port every time the loop is run:
void loop() {
    // Nothing to do here since HTTPServer
    // is running in a separate thread
    Serial.println("Hello world!");
    delay(1000);
}

 

Posted by Uli Köhler in Arduino, C/C++, PlatformIO

Dynamic short pulse generator using Arduino Mega2560 with serial control

This is a simplified version of our hybrid static/dynamic pulse generator. On the Arduino Mega2560 platform, it allows generating pulses from 750ns up to almost arbitrary lengths (limited only by the integer width) with a resolution of approx. 437.5ns

In order to control the pulse width, open a serial interface and type + to increase the pulse width or - to decrease the pulse width.

#include <Arduino.h>
#include <avr/io.h>
#include <ArduinoJson.h>

const int pulseAPin = 11;

#define PORT11 PORTB
#define PIN11 5
#define PIN11_MASK (1 << PIN11)

int pulseLength = 0;

/**
 * Pulse the output pin, for very short pulses.
 */
void PulseDynamic(int n) {
    cli();
    PORT11 |= PIN11_MASK;
    // Dynamic for loop
    for (;n >= 0; n--) {
        _NOP();
    }
    PORT11 &= ~PIN11_MASK;
    sei();
}

void setup()
{
    Serial.begin(115200);
    Serial.setTimeout(25);

    pinMode(pulseAPin, OUTPUT);
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
    PulseDynamic(pulseLength);
    // Process serial
    while(Serial.available() > 0) {
        int c = Serial.read();
        if(c == '+') {
            pulseLength++;
            Serial.println(pulseLength);
        } else if(c == '-') {
            pulseLength--;
            if(pulseLength < 0) {pulseLength = 0;}
            Serial.println(pulseLength);
        }
    }
    delay(50);
}

 

Posted by Uli Köhler in Arduino, C/C++

Hybrid static/dynamic Arduino Mega2560 single channel short pulse generator

This pulse generator firmware uses methods discussed e.g. in Short pulse generation with Arduino Uno Part 4: NOP for loops to generate both dynamic (for loops of NOP instructions) and static (template-based automatically unrolled) in a combined manner so you can select more or less any pulse width using a high resolution.

It doesn’t work 100% since there are still some pulse width jumps. However, it is still useful for many microsecond 5V pulse generation applications and might also be a useful technology demonstrator for hybrid static/dynamic pulsers using optimized integer template loop unrolling approaches.

In order to control the pulse width, open a serial interface and type + to increase the pulse width or - to decrease the pulse width.

This might work on Arduino Unos as well but my Uno had a broken serial interface chip so I used a ATMega2560 board.

// License: CC0 1.0 Universal
// By Uli Köhler (techoverflow.net)
#include <Arduino.h>
#include <avr/io.h>
#include <ArduinoJson.h>

#define PORT13 PORTB
#define PIN13 7
#define PIN13_MASK (1 << PIN13)

#define PORT11 PORTB
#define PIN11 5
#define PIN11_MASK (1 << PIN11)

int pulseLength = 1;

using PulseFunc = void (*)(int);

// Function pointer to void(int)
PulseFunc pulser = nullptr;
int pulserParam = 0; // Pre-computed parameter for the pulser function

void DoNothingPulser(int _) {
}

/**
 * Pulse the output pin, for very short pulses.
 * Will ONLY perform static (optimized) NOPs.
 * Will NOT perform dynamic (slower) NOP cycles
 * 
 * Hence, this function does not have any overhead from for loops.
 */
template<int nNOPs>
void PulseStatic(int _) {
    cli();
    PORT11 |= PIN11_MASK;
    // Static for loop (optimized out - template-driven)
    // Force unrolling of the loop
    // NOTE: Compiler will only unroll for n < 8
    for (int i = 0; i < min(nNOPs, 6); i++) {
        _NOP();
    }
    if(nNOPs > 6) {
        for (int i = 0; i < nNOPs - 6; i++) {
            _NOP();
        }
    }
    PORT11 &= ~PIN11_MASK;
    sei();
}

/**
 * Pulse the output pin, for very short pulses.
 * Will perform static (optimized) NOPs and
 * also dynamic (slower) NOP cycles
 */
template<int nNOPs>
void PulseDynamic(int dynamicNOPs) {
    cli();
    PORT11 |= PIN11_MASK;
    // Dynamic for loop (NOT optimized out - template-driven)
    for (int i = 0; i < dynamicNOPs; i++)
    {
        _NOP();
    }
    // Static for loop (optimized out - template-driven)
    // Force unrolling of the loop
    // NOTE: Compiler will only unroll for n < 8
    for (int i = 0; i < min(nNOPs, 6); i++) {
        _NOP();
    }
    if(nNOPs > 6) {
        for (int i = 0; i < nNOPs - 6; i++) {
            _NOP();
        }
    }
    PORT11 &= ~PIN11_MASK;
    sei();
}

PulseFunc staticPulsers[] = {
    DoNothingPulser,
    &PulseStatic<0>, // 0 NOPs
    &PulseStatic<1>, // 1 NOPs ...
    &PulseStatic<2>,
    &PulseStatic<3>,
    &PulseStatic<4>,
    &PulseStatic<5>,
    &PulseStatic<6>,
    &PulseStatic<7>,
    &PulseStatic<8>,
    &PulseStatic<9>,
    &PulseStatic<10>,
    &PulseStatic<11>
};

PulseFunc dynamicPulsers[] = {
    &PulseDynamic<0>,
    &PulseDynamic<1>,
    &PulseDynamic<2>,
    &PulseDynamic<3>,
    &PulseDynamic<4>,
    &PulseDynamic<5>,
    &PulseDynamic<6>,
    &PulseDynamic<7>,
    &PulseDynamic<8>,
    &PulseDynamic<9>,
    &PulseDynamic<10>,
    &PulseDynamic<11>
};

constexpr int A = 7;
constexpr int B = 6;

void ReconfigurePulse() {
    // Very short pulses are performed using only static
    if(pulseLength < A) {
        pulser = staticPulsers[pulseLength];
    } else {
        pulser = dynamicPulsers[(pulseLength - A) % B];
        pulserParam = (pulseLength - A) / B;
    }
}

void setup()
{
    Serial.begin(115200);
    Serial.setTimeout(25);

    ReconfigurePulse(); // with default pulseLength

    pinMode(11, OUTPUT);
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
    pulser(pulserParam);
    Serial.println(pulseLength);
    //ProcessSerialInput();
    // Wait until 50ms has passed since start
    while(Serial.available() > 0) {
        int c = Serial.read();
        if(c == '+') {
            pulseLength++;
            ReconfigurePulse();
        } else if(c == '-') {
            pulseLength--;
            if(pulseLength < 0) {pulseLength = 0;}
            ReconfigurePulse();
        }
    }
    delay(50);
}

 

 

Posted by Uli Köhler in Arduino, C/C++

How to list all C++ header files included by a source or header file recursively

You can use g++ -M to list all files included by a header file recursively:

gcc -M myheader.hpp

Often you want to ignore system header files from /usr/include etc – in that case, use -MM:

gcc -MM myheader.hpp

For example:

gcc -M /usr/include/boost/circular_buffer/base.hpp

will print:

base.o: /usr/include/boost/circular_buffer/base.hpp \
 /usr/include/stdc-predef.h /usr/include/boost/config.hpp \
 /usr/include/boost/config/user.hpp \
 /usr/include/boost/config/detail/select_compiler_config.hpp \
 /usr/include/boost/config/compiler/gcc.hpp /usr/include/c++/11/cstddef \
 /usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h \
 /usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h \
 /usr/include/features.h /usr/include/features-time64.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/timesize.h \
 /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/long-double.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h \
 /usr/include/c++/11/pstl/pstl_config.h \
 /usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h \
 /usr/include/boost/config/detail/select_stdlib_config.hpp \
 /usr/include/c++/11/version \
 /usr/include/boost/config/stdlib/libstdcpp3.hpp /usr/include/unistd.h \
 /usr/include/x86_64-linux-gnu/bits/posix_opt.h \
 /usr/include/x86_64-linux-gnu/bits/environments.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h \
 /usr/include/x86_64-linux-gnu/bits/time64.h \
 /usr/include/x86_64-linux-gnu/bits/confname.h \
 /usr/include/x86_64-linux-gnu/bits/getopt_posix.h \
 /usr/include/x86_64-linux-gnu/bits/getopt_core.h \
 /usr/include/x86_64-linux-gnu/bits/unistd_ext.h \
 /usr/include/linux/close_range.h \
 /usr/include/boost/config/detail/select_platform_config.hpp \
 /usr/include/boost/config/platform/linux.hpp /usr/include/c++/11/cstdlib \
 /usr/include/stdlib.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/x86_64-linux-gnu/bits/waitflags.h \
 /usr/include/x86_64-linux-gnu/bits/waitstatus.h \
 /usr/include/x86_64-linux-gnu/bits/floatn.h \
 /usr/include/x86_64-linux-gnu/bits/floatn-common.h \
 /usr/include/x86_64-linux-gnu/bits/types/locale_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/__locale_t.h \
 /usr/include/x86_64-linux-gnu/sys/types.h \
 /usr/include/x86_64-linux-gnu/bits/types/clock_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/clockid_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/time_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/timer_t.h \
 /usr/include/x86_64-linux-gnu/bits/stdint-intn.h /usr/include/endian.h \
 /usr/include/x86_64-linux-gnu/bits/endian.h \
 /usr/include/x86_64-linux-gnu/bits/endianness.h \
 /usr/include/x86_64-linux-gnu/bits/byteswap.h \
 /usr/include/x86_64-linux-gnu/bits/uintn-identity.h \
 /usr/include/x86_64-linux-gnu/sys/select.h \
 /usr/include/x86_64-linux-gnu/bits/select.h \
 /usr/include/x86_64-linux-gnu/bits/types/sigset_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/struct_timeval.h \
 /usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h \
 /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \
 /usr/include/x86_64-linux-gnu/bits/thread-shared-types.h \
 /usr/include/x86_64-linux-gnu/bits/pthreadtypes-arch.h \
 /usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h \
 /usr/include/x86_64-linux-gnu/bits/struct_mutex.h \
 /usr/include/x86_64-linux-gnu/bits/struct_rwlock.h /usr/include/alloca.h \
 /usr/include/x86_64-linux-gnu/bits/stdlib-float.h \
 /usr/include/c++/11/bits/std_abs.h \
 /usr/include/boost/config/detail/posix_features.hpp \
 /usr/include/boost/config/detail/suffix.hpp \
 /usr/include/boost/config/helper_macros.hpp \
 /usr/include/boost/config/detail/cxx_composite.hpp \
 /usr/include/boost/concept_check.hpp \
 /usr/include/boost/concept/assert.hpp \
 /usr/include/boost/config/workaround.hpp \
 /usr/include/boost/concept/detail/general.hpp \
 /usr/include/boost/preprocessor/cat.hpp \
 /usr/include/boost/preprocessor/config/config.hpp \
 /usr/include/boost/concept/detail/backward_compatibility.hpp \
 /usr/include/boost/concept/detail/has_constraints.hpp \
 /usr/include/boost/type_traits/integral_constant.hpp \
 /usr/include/boost/detail/workaround.hpp \
 /usr/include/boost/type_traits/conditional.hpp \
 /usr/include/c++/11/iterator \
 /usr/include/c++/11/bits/stl_iterator_base_types.h \
 /usr/include/c++/11/type_traits \
 /usr/include/c++/11/bits/stl_iterator_base_funcs.h \
 /usr/include/c++/11/bits/concept_check.h \
 /usr/include/c++/11/debug/assertions.h \
 /usr/include/c++/11/bits/stl_iterator.h \
 /usr/include/c++/11/bits/cpp_type_traits.h \
 /usr/include/c++/11/ext/type_traits.h /usr/include/c++/11/bits/move.h \
 /usr/include/c++/11/bits/ptr_traits.h /usr/include/c++/11/iosfwd \
 /usr/include/c++/11/bits/stringfwd.h \
 /usr/include/c++/11/bits/memoryfwd.h /usr/include/c++/11/bits/postypes.h \
 /usr/include/c++/11/cwchar /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-linux-gnu/11/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/wchar.h \
 /usr/include/x86_64-linux-gnu/bits/types/wint_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/mbstate_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
 /usr/include/x86_64-linux-gnu/bits/types/FILE.h \
 /usr/include/c++/11/bits/stream_iterator.h \
 /usr/include/c++/11/debug/debug.h \
 /usr/include/c++/11/bits/streambuf_iterator.h \
 /usr/include/c++/11/streambuf /usr/include/c++/11/bits/localefwd.h \
 /usr/include/x86_64-linux-gnu/c++/11/bits/c++locale.h \
 /usr/include/c++/11/clocale /usr/include/locale.h \
 /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/11/cctype \
 /usr/include/ctype.h /usr/include/c++/11/bits/ios_base.h \
 /usr/include/c++/11/ext/atomicity.h \
 /usr/include/x86_64-linux-gnu/c++/11/bits/gthr.h \
 /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h \
 /usr/include/pthread.h /usr/include/sched.h \
 /usr/include/x86_64-linux-gnu/bits/sched.h \
 /usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h \
 /usr/include/x86_64-linux-gnu/bits/cpu-set.h /usr/include/time.h \
 /usr/include/x86_64-linux-gnu/bits/time.h \
 /usr/include/x86_64-linux-gnu/bits/timex.h \
 /usr/include/x86_64-linux-gnu/bits/types/struct_tm.h \
 /usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h \
 /usr/include/x86_64-linux-gnu/bits/setjmp.h \
 /usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h \
 /usr/include/x86_64-linux-gnu/bits/pthread_stack_min-dynamic.h \
 /usr/include/x86_64-linux-gnu/c++/11/bits/atomic_word.h \
 /usr/include/x86_64-linux-gnu/sys/single_threaded.h \
 /usr/include/c++/11/bits/locale_classes.h /usr/include/c++/11/string \
 /usr/include/c++/11/bits/char_traits.h \
 /usr/include/c++/11/bits/stl_algobase.h \
 /usr/include/c++/11/bits/functexcept.h \
 /usr/include/c++/11/bits/exception_defines.h \
 /usr/include/c++/11/ext/numeric_traits.h \
 /usr/include/c++/11/bits/stl_pair.h \
 /usr/include/c++/11/bits/predefined_ops.h /usr/include/c++/11/cstdint \
 /usr/lib/gcc/x86_64-linux-gnu/11/include/stdint.h /usr/include/stdint.h \
 /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h \
 /usr/include/c++/11/bits/allocator.h \
 /usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h \
 /usr/include/c++/11/ext/new_allocator.h /usr/include/c++/11/new \
 /usr/include/c++/11/bits/exception.h \
 /usr/include/c++/11/bits/ostream_insert.h \
 /usr/include/c++/11/bits/cxxabi_forced.h \
 /usr/include/c++/11/bits/stl_function.h \
 /usr/include/c++/11/backward/binders.h \
 /usr/include/c++/11/bits/range_access.h \
 /usr/include/c++/11/initializer_list \
 /usr/include/c++/11/bits/basic_string.h \
 /usr/include/c++/11/ext/alloc_traits.h \
 /usr/include/c++/11/bits/alloc_traits.h \
 /usr/include/c++/11/bits/stl_construct.h /usr/include/c++/11/string_view \
 /usr/include/c++/11/bits/functional_hash.h \
 /usr/include/c++/11/bits/hash_bytes.h \
 /usr/include/c++/11/bits/string_view.tcc \
 /usr/include/c++/11/ext/string_conversions.h /usr/include/c++/11/cstdio \
 /usr/include/stdio.h /usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h \
 /usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h \
 /usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/c++/11/cerrno /usr/include/errno.h \
 /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \
 /usr/include/x86_64-linux-gnu/asm/errno.h \
 /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
 /usr/include/x86_64-linux-gnu/bits/types/error_t.h \
 /usr/include/c++/11/bits/charconv.h \
 /usr/include/c++/11/bits/basic_string.tcc \
 /usr/include/c++/11/bits/locale_classes.tcc \
 /usr/include/c++/11/system_error \
 /usr/include/x86_64-linux-gnu/c++/11/bits/error_constants.h \
 /usr/include/c++/11/stdexcept /usr/include/c++/11/exception \
 /usr/include/c++/11/bits/exception_ptr.h \
 /usr/include/c++/11/bits/cxxabi_init_exception.h \
 /usr/include/c++/11/typeinfo /usr/include/c++/11/bits/nested_exception.h \
 /usr/include/c++/11/bits/streambuf.tcc \
 /usr/include/boost/type_traits/conversion_traits.hpp \
 /usr/include/boost/type_traits/is_convertible.hpp \
 /usr/include/boost/type_traits/intrinsics.hpp \
 /usr/include/boost/type_traits/detail/config.hpp \
 /usr/include/boost/version.hpp \
 /usr/include/boost/type_traits/is_complete.hpp \
 /usr/include/boost/type_traits/declval.hpp \
 /usr/include/boost/type_traits/add_rvalue_reference.hpp \
 /usr/include/boost/type_traits/is_void.hpp \
 /usr/include/boost/type_traits/is_reference.hpp \
 /usr/include/boost/type_traits/is_lvalue_reference.hpp \
 /usr/include/boost/type_traits/is_rvalue_reference.hpp \
 /usr/include/boost/type_traits/remove_reference.hpp \
 /usr/include/boost/type_traits/is_function.hpp \
 /usr/include/boost/type_traits/detail/is_function_cxx_11.hpp \
 /usr/include/boost/type_traits/detail/yes_no_type.hpp \
 /usr/include/boost/type_traits/is_array.hpp \
 /usr/include/boost/static_assert.hpp \
 /usr/include/boost/type_traits/is_arithmetic.hpp \
 /usr/include/boost/type_traits/is_integral.hpp \
 /usr/include/boost/type_traits/is_floating_point.hpp \
 /usr/include/boost/type_traits/is_abstract.hpp \
 /usr/include/boost/type_traits/add_lvalue_reference.hpp \
 /usr/include/boost/type_traits/add_reference.hpp \
 /usr/include/c++/11/utility /usr/include/c++/11/bits/stl_relops.h \
 /usr/include/boost/type_traits/is_same.hpp \
 /usr/include/boost/concept/usage.hpp \
 /usr/include/boost/concept/detail/concept_def.hpp \
 /usr/include/boost/preprocessor/seq/for_each_i.hpp \
 /usr/include/boost/preprocessor/arithmetic/dec.hpp \
 /usr/include/boost/preprocessor/config/limits.hpp \
 /usr/include/boost/preprocessor/arithmetic/limits/dec_256.hpp \
 /usr/include/boost/preprocessor/arithmetic/inc.hpp \
 /usr/include/boost/preprocessor/arithmetic/limits/inc_256.hpp \
 /usr/include/boost/preprocessor/control/if.hpp \
 /usr/include/boost/preprocessor/control/iif.hpp \
 /usr/include/boost/preprocessor/logical/bool.hpp \
 /usr/include/boost/preprocessor/logical/limits/bool_256.hpp \
 /usr/include/boost/preprocessor/repetition/for.hpp \
 /usr/include/boost/preprocessor/debug/error.hpp \
 /usr/include/boost/preprocessor/facilities/empty.hpp \
 /usr/include/boost/preprocessor/detail/auto_rec.hpp \
 /usr/include/boost/preprocessor/detail/limits/auto_rec_256.hpp \
 /usr/include/boost/preprocessor/repetition/detail/for.hpp \
 /usr/include/boost/preprocessor/control/expr_iif.hpp \
 /usr/include/boost/preprocessor/tuple/eat.hpp \
 /usr/include/boost/preprocessor/repetition/detail/limits/for_256.hpp \
 /usr/include/boost/preprocessor/repetition/limits/for_256.hpp \
 /usr/include/boost/preprocessor/seq/seq.hpp \
 /usr/include/boost/preprocessor/seq/elem.hpp \
 /usr/include/boost/preprocessor/seq/limits/elem_256.hpp \
 /usr/include/boost/preprocessor/seq/size.hpp \
 /usr/include/boost/preprocessor/seq/limits/size_256.hpp \
 /usr/include/boost/preprocessor/seq/detail/is_empty.hpp \
 /usr/include/boost/preprocessor/logical/compl.hpp \
 /usr/include/boost/preprocessor/tuple/elem.hpp \
 /usr/include/boost/preprocessor/facilities/expand.hpp \
 /usr/include/boost/preprocessor/facilities/overload.hpp \
 /usr/include/boost/preprocessor/variadic/size.hpp \
 /usr/include/boost/preprocessor/facilities/check_empty.hpp \
 /usr/include/boost/preprocessor/variadic/has_opt.hpp \
 /usr/include/boost/preprocessor/variadic/limits/size_64.hpp \
 /usr/include/boost/preprocessor/tuple/rem.hpp \
 /usr/include/boost/preprocessor/tuple/detail/is_single_return.hpp \
 /usr/include/boost/preprocessor/variadic/elem.hpp \
 /usr/include/boost/preprocessor/variadic/limits/elem_64.hpp \
 /usr/include/boost/preprocessor/seq/enum.hpp \
 /usr/include/boost/preprocessor/seq/limits/enum_256.hpp \
 /usr/include/boost/preprocessor/comma_if.hpp \
 /usr/include/boost/preprocessor/punctuation/comma_if.hpp \
 /usr/include/boost/preprocessor/punctuation/comma.hpp \
 /usr/include/boost/concept/detail/concept_undef.hpp \
 /usr/include/boost/limits.hpp /usr/include/c++/11/limits \
 /usr/include/boost/core/allocator_access.hpp \
 /usr/include/boost/core/pointer_traits.hpp \
 /usr/include/boost/core/addressof.hpp \
 /usr/include/boost/core/empty_value.hpp \
 /usr/include/boost/type_traits/is_stateless.hpp \
 /usr/include/boost/type_traits/has_trivial_constructor.hpp \
 /usr/include/boost/type_traits/is_pod.hpp \
 /usr/include/boost/type_traits/is_scalar.hpp \
 /usr/include/boost/type_traits/is_enum.hpp \
 /usr/include/boost/type_traits/is_pointer.hpp \
 /usr/include/boost/type_traits/is_member_pointer.hpp \
 /usr/include/boost/type_traits/is_member_function_pointer.hpp \
 /usr/include/boost/type_traits/detail/is_member_function_pointer_cxx_11.hpp \
 /usr/include/boost/type_traits/is_default_constructible.hpp \
 /usr/include/boost/type_traits/is_volatile.hpp \
 /usr/include/boost/type_traits/has_trivial_copy.hpp \
 /usr/include/boost/type_traits/is_copy_constructible.hpp \
 /usr/include/boost/type_traits/is_constructible.hpp \
 /usr/include/boost/type_traits/is_destructible.hpp \
 /usr/include/boost/type_traits/has_trivial_destructor.hpp \
 /usr/include/boost/type_traits/is_class.hpp \
 /usr/include/boost/type_traits/is_empty.hpp \
 /usr/include/boost/type_traits/remove_cv.hpp \
 /usr/include/boost/type_traits/is_nothrow_move_constructible.hpp \
 /usr/include/boost/type_traits/enable_if.hpp \
 /usr/include/boost/type_traits/is_nothrow_move_assignable.hpp \
 /usr/include/boost/type_traits/has_trivial_move_assign.hpp \
 /usr/include/boost/type_traits/is_assignable.hpp \
 /usr/include/boost/type_traits/has_nothrow_assign.hpp \
 /usr/include/boost/type_traits/is_const.hpp \
 /usr/include/boost/move/adl_move_swap.hpp \
 /usr/include/boost/move/detail/workaround.hpp \
 /usr/include/boost/move/utility_core.hpp \
 /usr/include/boost/move/detail/config_begin.hpp \
 /usr/include/boost/move/core.hpp \
 /usr/include/boost/move/detail/config_end.hpp \
 /usr/include/boost/move/detail/meta_utils.hpp \
 /usr/include/boost/move/detail/meta_utils_core.hpp \
 /usr/include/boost/move/detail/addressof.hpp \
 /usr/include/boost/move/move.hpp /usr/include/boost/move/utility.hpp \
 /usr/include/boost/move/traits.hpp \
 /usr/include/boost/move/detail/type_traits.hpp \
 /usr/include/c++/11/cassert /usr/include/assert.h \
 /usr/include/boost/move/iterator.hpp \
 /usr/include/boost/move/detail/iterator_traits.hpp \
 /usr/include/boost/move/detail/std_ns_begin.hpp \
 /usr/include/boost/move/detail/std_ns_end.hpp \
 /usr/include/boost/move/algorithm.hpp \
 /usr/include/boost/move/algo/move.hpp \
 /usr/include/boost/move/detail/iterator_to_raw_pointer.hpp \
 /usr/include/boost/move/detail/to_raw_pointer.hpp \
 /usr/include/boost/move/detail/pointer_element.hpp \
 /usr/include/c++/11/algorithm /usr/include/c++/11/bits/stl_algo.h \
 /usr/include/c++/11/bits/algorithmfwd.h \
 /usr/include/c++/11/bits/stl_heap.h \
 /usr/include/c++/11/bits/stl_tempbuf.h \
 /usr/include/c++/11/bits/uniform_int_dist.h \
 /usr/include/c++/11/pstl/glue_algorithm_defs.h \
 /usr/include/c++/11/functional /usr/include/c++/11/tuple \
 /usr/include/c++/11/array /usr/include/c++/11/bits/uses_allocator.h \
 /usr/include/c++/11/bits/invoke.h /usr/include/c++/11/bits/refwrap.h \
 /usr/include/c++/11/bits/std_function.h \
 /usr/include/c++/11/unordered_map \
 /usr/include/c++/11/ext/aligned_buffer.h \
 /usr/include/c++/11/bits/hashtable.h \
 /usr/include/c++/11/bits/hashtable_policy.h \
 /usr/include/c++/11/bits/enable_special_members.h \
 /usr/include/c++/11/bits/node_handle.h \
 /usr/include/c++/11/bits/unordered_map.h \
 /usr/include/c++/11/bits/erase_if.h /usr/include/c++/11/vector \
 /usr/include/c++/11/bits/stl_uninitialized.h \
 /usr/include/c++/11/bits/stl_vector.h \
 /usr/include/c++/11/bits/stl_bvector.h \
 /usr/include/c++/11/bits/vector.tcc \
 /usr/include/c++/11/pstl/execution_defs.h /usr/include/c++/11/memory \
 /usr/include/c++/11/bits/stl_raw_storage_iter.h \
 /usr/include/c++/11/bits/align.h /usr/include/c++/11/bit \
 /usr/include/c++/11/bits/unique_ptr.h \
 /usr/include/c++/11/bits/shared_ptr.h \
 /usr/include/c++/11/bits/shared_ptr_base.h \
 /usr/include/c++/11/bits/allocated_ptr.h \
 /usr/include/c++/11/ext/concurrence.h \
 /usr/include/c++/11/bits/shared_ptr_atomic.h \
 /usr/include/c++/11/bits/atomic_base.h \
 /usr/include/c++/11/bits/atomic_lockfree_defines.h \
 /usr/include/c++/11/backward/auto_ptr.h \
 /usr/include/c++/11/pstl/glue_memory_defs.h /usr/include/c++/11/deque \
 /usr/include/c++/11/bits/stl_deque.h /usr/include/c++/11/bits/deque.tcc

 

Posted by Uli Köhler in C/C++

C++ S3 GetObject minimal streaming example using minio-cpp

#include <client.h>
#include <iostream>

using std::cout, std::endl;

int main(int argc, char* argv[]) {
  // Create S3 base URL.
  minio::s3::BaseUrl base_url("minio.mydomain.com");

  // Create credential provider.
  minio::creds::StaticProvider provider(
      "my-access-key", "my-secret-key");

  // Create S3 client.
  minio::s3::Client client(base_url, &provider);
  std::string bucket_name = "my-bucket";

  // Build arguments object
  minio::s3::GetObjectArgs args;
  args.bucket = bucket_name;
  args.object = "my-object.txt";
  args.datafunc = [](minio::http::DataFunctionArgs args) -> bool {
    // This function will be called for every data chunk of the object
    cout << args.datachunk;
    return true;
  };

  // Perform the request (calling datafunc for every chunk)
  minio::s3::GetObjectResponse resp = client.GetObject(args);
  // Handle error (if any)
  if (resp) {
    cout << endl // end line after file content
         << "data of my-object is received successfully" << endl;
  } else {
    cout << "Error during GetObject(): " << resp.Error().String() << endl;
  }

  return EXIT_SUCCESS;
}

 

Posted by Uli Köhler in C/C++, S3

C++ S3 ListObjects minimal example using minio-cpp

#include <client.h>

int main(int argc, char* argv[]) {
  // Create S3 base URL.
  minio::s3::BaseUrl base_url("minio.mydomain.com");

  // Create credential provider.
  minio::creds::StaticProvider provider(
      "my_access_key", "my_secret_key");

  // Create S3 client.
  minio::s3::Client client(base_url, &provider);
  std::string bucket_name = "my-bucket";

  minio::s3::ListObjectsArgs args;
  args.bucket = bucket_name;
  // Optional prefix filter
  args.prefix = "folder/";

  minio::s3::ListObjectsResult result = client.ListObjects(args);
  for (; result; result++) {
      minio::s3::Item item = *result;
      if (!item) {
        throw std::runtime_error("Error during ListObjects(): " + item.Error().String());
      }
      std::cout << item.name << std::endl;
  }

  return EXIT_SUCCESS;
}

 

Posted by Uli Köhler in C/C++, S3

How to fix C++ linking error: undefined reference to symbol ‘crc32’

Problem:

While trying to compile your C++ program, during the linking stage, you see an error message such as

/bin/ld: minio-cpp/src/utils.o: undefined reference to symbol 'crc32'
/bin/ld: /lib/x86_64-linux-gnu/libz.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

Solution:

The crc32 symbol is defined in zlib. Hence, you need to link zlib by adding

-lz

to your linker flags. If you don’t know where your linker flags are, try just adding it to your compiler flags.

Posted by Uli Köhler in C/C++, GCC errors

How to fix C++ “fatal error: INIReader.h: No such file or directory” on Ubuntu

Problem:

While trying to compile your C++ project, you see an error message such as

minio-cpp/include/providers.h:19:10: fatal error: INIReader.h: No such file or directory
   19 | #include <INIReader.h>
      |          ^~~~~~~~~~~~~
compilation terminated.

Solution:

You need to install the inih library. On Ubuntu or Debian, you can do that using

sudo apt -y install libinih-dev

 

Posted by Uli Köhler in C/C++, GCC errors

How to fix C++ “fatal error: curlpp/Easy.hpp: No such file or directory” on Ubuntu

Problem:

While trying to compile your C++ project, you see an error message such as

minio-cpp/include/http.h:21:10: fatal error: curlpp/Easy.hpp: No such file or directory
   21 | #include <curlpp/Easy.hpp>
      |          ^~~~~~~~~~~~~~~~~
compilation terminated.

Solution:

You need to install the curlpp library, a C++ wrapper around libcurl. On Ubuntu or Debian, you can do that using

sudo apt -y install libcurlpp-dev

 

Posted by Uli Köhler in C/C++, GCC errors

How to fix C++ “fatal error: pugixml.hpp: No such file or directory” on Ubuntu

Problem:

While trying to compile your C++ project, you see an error message such as

minio-cpp/include/select.h:19:10: fatal error: pugixml.hpp: No such file or directory
   19 | #include <pugixml.hpp>

Solution:

You need to install the PugiXML library. On Ubuntu or Debian, you can do that using

sudo apt -y install libpugixml-dev

 

Posted by Uli Köhler in C/C++, GCC errors

How to fix C++ error: ‘put_time’ is not a member of ‘std’

Problem:

While trying to compile your C++ application, you see an error message such as

src/HTTPServer.cpp:12:16: error: 'put_time' is not a member of 'std'
     ss << std::put_time(std::localtime(&localTime), "%FT%H-%M-%SZ");;
                ^~~~~~~~

Solution:

At the top of the file where this error occured, you need to add

#include <iomanip>

iomanip contains std::put_time() among other functionality.

Posted by Uli Köhler in C/C++, GCC errors