CodeBlanks Logo Icon CodeBlanks

Putting it together

Combine all expert topics into a working mini app.

C-compatible interface with extern "C"

The C++ compiler applies name mangling to function names (for example, engine_report becomes _Z13engine_reportv). This is needed for overloading, but it makes calls from C or other languages harder. An extern "C" declaration disables mangling.

In this final lesson we combine every expert topic: Factorial<5>::value (TMP), Engine::parallelSum() (atomic), the fake register access (volatile) and an extern "C" interface (ABI). The result is a single report function callable from C as well.

Combining all pieces

In the final step we combine all pieces inside an extern "C" function. This function can be called from C as well, because no mangling is applied to its name. Inside it we use the compile-time factorial and the parallel sum together.

Example: extern "C" int engine_report() { return Factorial<5>::value + Engine::parallelSum(); }. This function returns 120 + 36 = 156. We call it from main with std::cout << engine_report();. This way all expert topics meet in a single ABI interface.

Practice Add the extern "C" engine_report function

Take the previous lesson's solution. After the Factorial template add extern "C" int engine_report() with body return Factorial<5>::value + Engine::parallelSum();. In main after the register output add std::cout << engine_report();.

Starter code

main.cpp
#include <iostream>
#include <atomic>
#include <thread>
#include <cstdint>

class Engine {
public:
    static const int Version = 1;
    static int parallelSum() {
        std::atomic<int> total{0};
        std::thread t1([&]() { for (int i = 1; i <= 4; ++i) total += i; });
        std::thread t2([&]() { for (int i = 5; i <= 8; ++i) total += i; });
        t1.join();
        t2.join();
        return total.load();
    }
    static std::uint32_t readRegister(volatile std::uint32_t* reg) {
        return *reg;
    }
    static void writeRegister(volatile std::uint32_t* reg, std::uint32_t value) {
        *reg = value;
    }
};

template <int N>
struct Factorial {
    static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static const int value = 1;
};

// Add the C-compatible report function here

int main() {
    std::cout << "Ready" << std::endl;
    std::cout << Factorial<5>::value << std::endl;
    std::cout << Engine::parallelSum() << std::endl;
    volatile std::uint32_t reg = 0;
    Engine::writeRegister(&reg, 64);
    std::cout << Engine::readRegister(&reg) << std::endl;
    // Add the engine_report call
    return 0;
}

Sample solution

main.cpp
#include <iostream>
#include <atomic>
#include <thread>
#include <cstdint>

class Engine {
public:
    static const int Version = 1;
    static int parallelSum() {
        std::atomic<int> total{0};
        std::thread t1([&]() { for (int i = 1; i <= 4; ++i) total += i; });
        std::thread t2([&]() { for (int i = 5; i <= 8; ++i) total += i; });
        t1.join();
        t2.join();
        return total.load();
    }
    static std::uint32_t readRegister(volatile std::uint32_t* reg) {
        return *reg;
    }
    static void writeRegister(volatile std::uint32_t* reg, std::uint32_t value) {
        *reg = value;
    }
};

template <int N>
struct Factorial {
    static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static const int value = 1;
};

extern "C" int engine_report() {
    return Factorial<5>::value + Engine::parallelSum();
}

int main() {
    std::cout << "Ready" << std::endl;
    std::cout << Factorial<5>::value << std::endl;
    std::cout << Engine::parallelSum() << std::endl;
    volatile std::uint32_t reg = 0;
    Engine::writeRegister(&reg, 64);
    std::cout << Engine::readRegister(&reg) << std::endl;
    std::cout << engine_report();
    return 0;
}

Expected output

Ready
120
36
64
156

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What does extern "C" do?

main.cpp
extern "C" int engine_report();
  • It hides names
  • It changes the operating system
  • It disables name mangling Correct answer
  • It increases runtime checks

Explanation: extern "C" prevents name mangling on the function name.

2 Match each piece to its role

Term Meaning
extern "C" C-compatible interface
Factorial<5>::value Compile-time constant
std::atomic<int> Parallel safe counter
volatile Hardware register access

3 Complete the extern "C" declaration

Question
extern "C" ____ engine_report() { return Factorial<5>::value + Engine::parallelSum(); }
Answer
extern "C" int engine_report() { return Factorial<5>::value + Engine::parallelSum(); }

Explanation: The return type is int; it returns a number.

All lessons in Expert