C/C++

How to add conan CMake build definition

When building a library using conan, this is the default conanfile.py definition for building using CMake

cmake = CMake(self)
cmake.configure(source_folder="hello")
cmake.build()

You can easily add definitions like this:

cmake.definitions["MY_FLAG"] = "1"

This will generate -DMY_FLAG=1 when calling CMake

Full example:

cmake = CMake(self)
cmake.definitions["USE_SYSTEM_CPR"] = "1
cmake.configure(source_folder="elasticlient")"
cmake.build()

Note that you need to add all cmake.definitions calls before calling cmake.configure()

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

How to fix CMake Protobuf “FindThreads only works if either C or CXX language is enabled”

Problem:

When trying to configure your CMake project using

find_package(Protobuf REQUIRED)

you see an error message like

CMake Error at /usr/share/cmake-3.16/Modules/FindThreads.cmake:49 (message):
  FindThreads only works if either C or CXX language is enabled
Call Stack (most recent call first):
  /usr/share/cmake-3.16/Modules/FindProtobuf.cmake:420 (find_package)
  CMakeLists.txt:7 (find_package)

-- Configuring incomplete, errors occurred!

Solution:

You need to put your

project(MyProject)

line before the

find_package(Protobuf REQUIRED)

line. If you don’t have a project() line, create one.

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

How to read last byte from file in C++

Use fseek() with offset -1 and mode SEEK_END:

fseek(myfile, -1, SEEK_END);

Ready-to-use function

#include <cstdio>
#include <optional>

/**
 * Read the last byte of a given 
 */
std::optional<char> readLastByteOfFile(const char* filename) {
    FILE* fin = fopen(filename, "r");
    if(fin == nullptr) {
        return std::nullopt;
    }
    fseek(fin, -1, SEEK_END);
    char lastByte;
    if(fread(&lastByte, 1, 1, fin) == 0) {
        return std::nullopt;
    }
    fclose(fin);
    return lastByte;
}

Complete example program

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <optional>

/**
 * Read the last byte of a given 
 */
std::optional<char> readLastByteOfFile(const char* filename) {
    FILE* fin = fopen(filename, "r");
    if(fin == nullptr) {
        return std::nullopt;
    }
    fseek(fin, -1, SEEK_END);
    char lastByte;
    if(fread(&lastByte, 1, 1, fin) == 0) {
        return std::nullopt;
    }
    fclose(fin);
    return lastByte;
}

int main(int argc, char** argv) {
    if(argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <input file to read from>" << std::endl;
    }

    auto lastByte = readLastByteOfFile(argv[1]);
    if(lastByte) {
        std::cout << lastByte.value() << std::endl;
    } else {
        std::cout << "File error or empty" << std::endl;
    }
}

Generate test data with:

echo -n "abcd" > test.txt
touch test2.txt

Compile using:

g++ -o read-last-byte read-last-byte.cpp --std=c++17

Test using:

$ ./test-last-byte test1.txt
d
$ ./test-last-byte test2.txt
File error or no last byte
Posted by Uli Köhler in C/C++

How to pass flags to RapidXML xml_document::parse()

Use the template argument (<>) like this:

doc.parse<rapidxml::parse_non_destructive>(data);

Full example:

// Create & parse document
xml_document<> doc;
try {
    doc.parse<rapidxml::parse_non_destructive>(data);
} catch(rapidxml::parse_error& ex) {
    cerr << "XML Parse error in " << filename << endl; 
    return;
}

 

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

How to fix build ‘lz4 library not found, compiling without it’

Problem:

When compiling a piece of software – for example in your Dockerfile or on your PC – you see a warning message like

lz4 library not found, compiling without it

Solution:

Install liblz4, which is a library for a compression algorithm. On Ubuntu/Debian based systems you can install it using

sudo apt -y install liblz4-dev

In your Dockerfile, install using

RUN apt update && apt install -y liblz4-dev && rm -rf /var/lib/apt/lists/*

Otherwise, refer to the liblz4 GitHub page.

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

How to catch ANY exception in gdb

In gdb, run

catch throw

in order to break on any exception that is being thrown.

If you want to only break on a specific exception type instead, use

catch throw [exception type]

 

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

How to compile boost unit test program using CMake

Add this to your CMakeLists.txt:

#
# Compile test suite
#
find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)

add_executable(test_myprogram
    tests/MyTest.cpp
)
target_include_directories(test_myprogram PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include")
target_compile_features(test_myprogram PRIVATE cxx_std_17)

target_link_libraries(test_myprogram
                      ${Boost_FILESYSTEM_LIBRARY}
                      ${Boost_SYSTEM_LIBRARY}
                      ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                      )
add_test(test_myprogram test_myprogram)
# make "make test" run the test program
add_custom_target(test
     DEPENDS myprogram
     COMMAND ./test_myprogram
)

In order to build the program and the test, run

make

In order to run the tests, use

make test
Posted by Uli Köhler in Boost, C/C++, CMake

How to fix CMake error Could not find a package configuration file provided by “boost_unit_test_framework”

Problem:

When compiling your CMake-based C++

CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:117 (find_package):
  Could not find a package configuration file provided by
  "boost_unit_test_framework" (requested version 1.71.0) with any of the
  following names:

    boost_unit_test_frameworkConfig.cmake
    boost_unit_test_framework-config.cmake

  Add the installation prefix of "boost_unit_test_framework" to
  CMAKE_PREFIX_PATH or set "boost_unit_test_framework_DIR" to a directory
  containing one of the above files.  If "boost_unit_test_framework" provides
  a separate development package or SDK, be sure it has been installed.
Call Stack (most recent call first):
  /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:182 (boost_find_component)
  /usr/share/cmake-3.16/Modules/FindBoost.cmake:443 (find_package)
  OCCUtils/CMakeLists.txt:58 (find_package)


-- Configuring incomplete, errors occurred!

Solution:

The error message is trying to tell you that you don’t have the boost unit test library installed (or CMake can’t find it).

On Ubuntu, for example, install it using

sudo apt -y install libboost-test-dev

On Windows you can install it using the prebuilt boost binaries for Windows.

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

How to fix CMake error Could not find a package configuration file provided by “boost_filesystem”

Problem:

When compiling your CMake-based C++

CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:117 (find_package):
  Could not find a package configuration file provided by "boost_filesystem"
  (requested version 1.71.0) with any of the following names:

    boost_filesystemConfig.cmake
    boost_filesystem-config.cmake

  Add the installation prefix of "boost_filesystem" to CMAKE_PREFIX_PATH or
  set "boost_filesystem_DIR" to a directory containing one of the above
  files.  If "boost_filesystem" provides a separate development package or
  SDK, be sure it has been installed.
Call Stack (most recent call first):
  /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:182 (boost_find_component)
  /usr/share/cmake-3.16/Modules/FindBoost.cmake:443 (find_package)
  CMakeLists.txt:58 (find_package)

Solution:

The error message is trying to tell you that you don’t have the boost filesystem library installed (or CMake can’t find it).

On Ubuntu, for example, install it using

sudo apt -y install libboost-filesystem-dev

On Windows you can install it using the prebuilt boost binaries for Windows.

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

Minimal Boost C++ Unit test example

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE( test1 )
{
    BOOST_CHECK( 2 == 1 );
}

 

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

How to ping gateway in ESP32

You can use the ESP32Ping library in order to easily ping the current gateway IP:

if(Ping.ping(WiFi.gatewayIP(), 1)) { // 1: Just one ping
  // TODO What to do on ping succes
  // Example: Print response time 
  Serial.print(Ping.averageTime()); // Unit: ms
  Serial.println(" ms");
} else {
  // TODO What to do if ping failed?
}

Full example:

#include <Arduino.h>
#include <WiFi.h>

#include <ESP32Ping.h>

void waitForWiFiConnectOrReboot(bool printOnSerial=true) {
  uint32_t notConnectedCounter = 0;
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      if(printOnSerial) {
        Serial.println("Wifi connecting...");
      }
      notConnectedCounter++;
      if(notConnectedCounter > 50) { // Reset board if not connected after 5s
          if(printOnSerial) {
            Serial.println("Resetting due to Wifi not connecting...");
          }
          ESP.restart();
      }
  }
  if(printOnSerial) {
    // Print wifi IP addess
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
  }
}

#define LED_BUILTIN 2

void setup() {
  Serial.begin(115200);
  WiFi.begin("MyWifiSSID", "MyWifiPassword");
  // Wait for wifi to be connected
  waitForWiFiConnectOrReboot();
  // Initialize LED
  pinMode(LED_BUILTIN,OUTPUT);
}

void loop() {
  if(Ping.ping(WiFi.gatewayIP())) {
    digitalWrite(LED_BUILTIN,HIGH);
    Serial.print(Ping.averageTime());
    Serial.println(" ms");
  } else {
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("Error :(");
  }

}

Example output

6.12 ms
5.12 ms
5.11 ms
5.16 ms
4.95 ms
4.88 ms
4.84 ms
7.67 ms
5.01 ms
4.87 ms
4.81 ms
4.80 ms
4.85 ms
5.08 ms
5.76 ms
4.54 ms
5.12 ms
2.77 ms
4.88 ms
4.84 ms
6.07 ms
5.08 ms
4.91 ms
6.04 ms
4.88 ms
4.98 ms
6.43 ms
8.18 ms
4.93 ms
5.17 ms
4.97 ms
5.46 ms
5.88 ms
4.78 ms
4.88 ms
6.03 ms
4.84 ms
5.70 ms
5.94 ms
7.25 ms
5.07 ms
4.78 ms
5.51 ms
4.99 ms
5.04 ms
4.79 ms
4.94 ms
4.81 ms
5.97 ms
5.85 ms
4.83 ms
4.80 ms
4.80 ms
6.29 ms
4.99 ms
5.04 ms
9.21 ms
5.20 ms
6.05 ms
6.14 ms
5.03 ms
4.90 ms
7.22 ms
5.06 ms
4.94 ms
9.03 ms
5.13 ms
11.97 ms
6.32 ms
6.12 ms
4.92 ms
4.92 ms
6.01 ms
4.96 ms
4.98 ms
4.94 ms
6.08 ms
6.11 ms
4.93 ms
5.05 ms
5.78 ms
4.47 ms
6.28 ms
5.02 ms
5.13 ms
5.11 ms
5.19 ms
8.89 ms
5.76 ms
5.18 ms
8.08 ms
4.97 ms
4.89 ms
4.70 ms
5.40 ms
7.46 ms
5.09 ms
4.95 ms
4.96 ms
5.01 ms
5.01 ms
4.89 ms
6.22 ms
6.76 ms
6.92 ms
6.10 ms
9.61 ms
5.29 ms
6.13 ms
5.15 ms
5.02 ms
5.03 ms
5.01 ms
6.13 ms
4.78 ms
3.90 ms
6.27 ms
8.07 ms
5.94 ms
4.50 ms
6.13 ms
4.99 ms
6.07 ms
4.80 ms
4.84 ms
4.95 ms
4.95 ms
6.78 ms
4.88 ms

 

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

How to fix GCC error: implicit declaration of function …

Problem:

While trying to compile your C/C++ program, you see an error message like

../src/main.c:48:9: error: implicit declaration of function 'StartBenchmark' [-Werror=implicit-function-declaration]
         StartBenchmark();

Solution:

implicit declaration of function means that you are trying to use a function that has not been declared. In our example above, StartBenchmark is the function that is implicitly declared.

This is how you call a function:

StartBenchmark();

This is how you declare a function:

void StartBenchmark();

The following bullet points list the most common reasons and how to fix them:

  1. Missing #include: Check if the header file that contains the declaration of the function is #included in each file where you call the function (especially the file that is listed in the error message), before the first call of the function (typically at the top of the file). Header files can be included via other headers,
  2. Function name typo: Often the function name of the declaration does not exactly match the function name that is being called. For example, startBenchmark() is declared while StartBenchmark() is being called. I recommend to fix this by copy-&-pasting the function name from the declaration to wherever you call it.
  3. Bad include guard: The include guard that is auto-generated by IDEs often looks like this:
    #ifndef _EXAMPLE_FILE_NAME_H
    #define _EXAMPLE_FILE_NAME_H
    // ...
    #endif

    Note that the include guard definition _EXAMPLE_FILE_NAME_H is not specific to the header filename that we are using (for example Benchmark.h). Just the first of all header file names wil

  4. Change the order of the #include statements: While this might seem like a bad hack, it often works just fine. Just move the #include statements of the header file containing the declaration to the top. For example, before the move:
    #include "Benchmark.h"
    #include "other_header.h"

    after the move:

    #include "Benchmark.h"
    #include "other_header.h"
Posted by Uli Köhler in C/C++, GCC errors

How to measure performance on the PIC32

First, use MPLab Harmony Configurator 3 to enable the CORETIMER module for your project. No special configuration is neccessary.

The PIC32 Core Timer always runs at half the CPU frequency. For example, if the CPU is running at 200 MHz, the Core Timer will run at 100 MHz.

You an then use

uint32_t CORETIMER_CounterGet();

to get the current value of the core timer. Additionally, you can get the frequency of the Core Timer in Hz using

uint32_t CORETIMER_FrequencyGet();

Use the following snippet to measure how long it takes to run a specific function:

uint32_t t0 = CORETIMER_CounterGet();
run_my_func();
uint32_t t1 = CORETIMER_CounterGet();

After that, you can compute the number of seconds it took to run the function using e.g.

uint32_t tdelta = t1 - t0;
float seconds = tdelta / (float)CORETIMER_FrequencyGet();

or the number of milliseconds:

uint32_t tdelta = t1 - t0;
float milliseconds = tdelta / (CORETIMER_FrequencyGet() / 1000.0);

or the number of microseconds:

uint32_t tdelta = t1 - t0;
float microseconds = tdelta / (CORETIMER_FrequencyGet() / 1000000.0);

 

Posted by Uli Köhler in C/C++, Electronics, Embedded

How to fix GCC lots of undefined reference to std:: functions

Problem:

When trying to compile your C++ application, you see lots of undefined reference to messages like

AutoBenchmark.cpp:(.text+0x6a): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x81): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x8a): undefined reference to `std::chrono::_V2::system_clock::now()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0xcd): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0xe6): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::~AutoBenchmark()':
AutoBenchmark.cpp:(.text+0x17e): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x18e): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::Record(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
AutoBenchmark.cpp:(.text+0x1db): undefined reference to `std::chrono::_V2::system_clock::now()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::Record(char const*)':
AutoBenchmark.cpp:(.text+0x252): undefined reference to `std::allocator<char>::allocator()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x288): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x294): undefined reference to `std::allocator<char>::~allocator()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x2b9): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x2ce): undefined reference to `std::allocator<char>::~allocator()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::Print()':
AutoBenchmark.cpp:(.text+0x316): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::length() const'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x332): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x337): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x344): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x572): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x577): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x59c): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x5ab): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x5c2): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x5d1): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x607): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x60c): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x631): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x640): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x657): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x666): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x69c): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6a1): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6c6): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6d5): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6ec): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6fb): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x731): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x736): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x75b): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x76a): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x781): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x790): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x7c6): undefined reference to `std::cout'

Solution:

You need to link the stdc++ library by adding -lstdc++ to your compiler/linker flags.

For example, instead of

gcc -o myprogram *.c

use

gcc -o myprogram *.c -lstdc++

 

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

How to fix GCC error: expected constructor, destructor, or type conversion before __declspec(dllexport)

Problem:

When trying to compile an application on Linux, you see a compiler error message like

myheader.h:23:12: error: expected constructor, destructor, or type conversion before ‘(’ token
   23 |  __declspec(dllexport) int myfunc(

Solution:

__declspec(dllexport) is a Windows-specific feature and not available on Linux. In order to fix it in a compatible way, add this code either in a header that is included in every file containing __declspec(dllexport) or add it in each file where the error occurs:

#ifdef __linux__
#define __declspec(v)
#endif

This will basically ignore any __declspec() call on the preprocessor level.

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

How to fix GCC undefined reference to `sqrt’

Problem:

When trying to compile your application using gcc, you see an error message like

/usr/bin/ld: /tmp/ccxPIowU.o: in function `run_mymath':
mathstuff.c:(.text+0x15d): undefined reference to `sqrt'

Solution:

You need to link the math library using the -lm flag (-lxxx means: “link the xxx library”, i.e. -lm means “link the m” library)

For example, instead of

gcc -o myprogram *.c

use

gcc -o myprogram *.c -lm

 

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

How to fix GCC undefined reference to `_finite’ or implicit declaration of function ‘_finite’

Problem:

If you’re trying to compile Windows code on Linux, you will often see messages like

lmmin.c:261:10: warning: implicit declaration of function ‘_finite’; did you mean ‘finite’? [-Wimplicit-function-declaration]
  116 |     if(!_finite(myvalue)){

or

/usr/bin/ld: mymath.c:(.text+0x1057): undefined reference to `_finite'

and your code won’t compile.

Solution:

_finite is a function that is only available on Windows. In order to use it on Linux using GCC or G++, one option is to use isfinite() from math.h:

#include <math.h>

#define _finite(v) (isfinite((v)))

In case that function is not available (like on some Microcontroller platforms), you can use __builtin_isfinite(). Note that glibc defines isfinite() as an alias for __builtin_isfinite(). Use it like this:

#define _finite(v) (__builtin_isfinite(v))

In case you want to have code that is compatible with both platforms (Windows and Linux), use

#ifdef __linux__
#define _finite(v) (__builtin_isfinite(v))
#endif

or

#include <math.h>

#ifdef __linux__
#define _finite(v) (isfinite((v)))
#endif

 

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

Minimal ESP32 NTP client example using NTPClient_Generic and PlatformIO

Example of using NTPClient_Generic

main.cpp

#include <Arduino.h>
#include <WiFi.h>
#include <NTPClient_Generic.h>

#define TIME_ZONE_OFFSET_HRS 1 // UTC+1 for Germany, winter time
#define NTP_UPDATE_INTERVAL_MS 60000L // Update every 60s automatically
WiFiUDP ntpUDP;
NTPClient ntpClient(ntpUDP, "europe.pool.ntp.org", (3600 * TIME_ZONE_OFFSET_HRS), NTP_UPDATE_INTERVAL_MS);

void ntpUpdateTask(void* param) {
  while(true) {
    // Update NTP. This will only ACTUALLY update if
    // the NTP client has not updated for NTP_UPDATE_INTERVAL_MS
    ntpClient.update();
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void setup() {
  Serial.begin(115200);
  // Force reset Wifi to avoid failure to connect
  WiFi.disconnect(true);
  // Set hostname
  WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
  WiFi.setHostname("ESP-NTP");
  // Connect to Wifi
  WiFi.begin("MyWifiSSID", "MyWifiPassword");
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      Serial.println("Wifi connecting...");
  }

  // Start NTP client (i.e. start listening for NTP packets)
  ntpClient.begin();
  // Create task to automatically update NTP in the background
  xTaskCreate(ntpUpdateTask, "NTP update", 2000, nullptr, 1, nullptr);
}

void loop() {
  delay(1000);
  if (ntpClient.updated()) {
    Serial.println("# Time in sync with NTP server");
  } else {
    Serial.println("# TIME NOT IN SYNC WITH NTP SERVER !");
    return; // Do not print time
  }

  Serial.println("UTC : " + ntpClient.getFormattedUTCTime());
  Serial.println("UTC : " + ntpClient.getFormattedUTCDateTime());
  Serial.println("LOC : " + ntpClient.getFormattedTime());
}

platformio.ini

[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
lib_deps =
    khoih.prog/NTPClient_Generic @ ^3.2.2
    Time

Example output:

Wifi connecting...
Wifi connecting...
Wifi connecting...
# TIME NOT IN SYNC WITH NTP SERVER !
# Time in sync with NTP server
UTC : 01:22:07
UTC : 01:22:07 Sun 07 Feb 2021
LOC : 02:22:07
# Time in sync with NTP server
UTC : 01:22:08
UTC : 01:22:08 Sun 07 Feb 2021
LOC : 02:22:08
# Time in sync with NTP server
UTC : 01:22:09
UTC : 01:22:09 Sun 07 Feb 2021
LOC : 02:22:09

 

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

How to get current gateway IP address on ESP8266/ESP32

In order to get the current gateway IP address on the ESP8266 or ESP32, use:

WiFi.gatewayIP();

In order to print the gateway IP address on the serial port, use

Serial.println("Gateway IP address: ");
Serial.println(WiFi.gatewayIP());

In order to get the gateway IP address as string, use

String gatewayIP = WiFi.gatewayIP().toString();

 

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