Search code examples
c++clinkerabilinkage

Why are C++ features unable to be used in extern "C" prototypes but able to be used in the implementation to link in C?


Functions in extern "C" are interpreted in C manners, e.g. no name mangling. However, why do C++ features, such as STL, std::string, smart pointer and so on, can be used in the function definition but cannot be used in the function declaration (to link with other C code)?

For example, I want to use std::vector in extern "C". As far as I know, if it's used in the implementation, the .obj file will have such instructions to jump to the ctor, etc; if it's used in the prototypes, it should do so too, and there seems to be no difference between them.

Besides, there is a related question for currently I'm studying ABI. What's the relationship between so-called ABI and language linkage in C++? How does ABI influence linking with extern "C" C++ code in C?


Solution

  • Why are C++ features unable to be used in extern "C" prototypes but able to be used in the implementation to link in C?

    Because the C compiler doesn't understand C++ specific code.

    The implementation of the extern "C" function that uses C++ classes is compiled with a C++ compiler.

    The C compiler only sees the function declaration, which can not contain C++ specific things, like std::vectors.

    header.h - seen by both C and C++ compilers

    #pragma once
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    int foo(const char*);          // works in both C and C++
    // int bar(std::vector<int>&); // a C compiler can't compile this
    
    #ifdef __cplusplus
    }
    #endif
    

    impl.cpp - never seen by the C compiler, only the C++ compiler

    #include "header.h"
    
    int foo(const char* something) {
        std::vector<int> bar;
        // use bar and do stuff
        return result;
    }