What is the effect of extern ‘C' in C++?

What is the effect of extern ‘C' in C++?

C++ offers name mangling to provide functionalities such as function overloading and namespaces, but this creates a problem when linking with C functions that are not name-mangled. Extern ‘C’ disables the name-mangling facility, thus ensuring the callbacks that work the same in C and C++. It bridges the gap between calling C libraries from C++ code and cross-language interoperability. 

In this article, we will discuss extern ‘C’ in C++, its effects, implementation in C++, when to use and when not to use it, common mistakes, and best practices.

Table of Contents:

What do you mean by extern ‘C’ in C++?

Extern ‘C’ is a linkage specification in C++ that tells the compiler to use C-style naming conventions for the declared functions or variables. This prevents name mangling, allowing C++ code to link with C functions seamlessly. It is commonly used when integrating C libraries with C++ or exposing C++ functions to C programs.

Name Mangling in C++

Name mangling refers to the process by which the C++ compiler modifies function and variable names to include additional information about their function signatures, namespaces, and class memberships. This provides better working of some C++ features, namely function overloading, namespaces, and class member functions that do not exist in C. Also, name mangling may cause several troubles in linking C++ code to C functions that do not have name mangling.

Why Does C++ Use Name Mangling?

C has a simple symbol table where function names need to be unique, however, C++ allows:

  1. Function Overloading (same function name with different parameters).
  2. Namespaces (functions with the same name in different namespaces).
  3. Member Functions (functions inside a class).

To distinguish between these functions, C++ uses mangling that adds extra bits of information into the name.

Example:

Cpp

Output:

The code shows how name mangling works in C++ due to which the compiler modifies function names to support function overloading.

Effect of extern ‘C’ in C++

Some of the main effects of extern ‘C’ in C++ include:

1. Prevents Name Mangling

When a function is declared within extern ‘C’, the C++ compiler does not apply the name mangling. Thus, the function name remains in simple C-style, making it compatible with C code.

You can also consider it in simple terms that C++ compilers modify function names to support function overloading and namespaces (name mangling).

Example:

Cpp

Output:

The code shows how the extern C is used to prevent name mangling in C++.

2. Enables Linking with C Code

If a C++ program tries to call a C function without extern 'C', the linker will not find the function due to mangled names.  So, the use of extern 'C' is important.

Example:

The example given below includes both the C and C++ code in one place, but in real use, you should keep them in separate files.

File 1: c_code.c 

C

File 2: main.cpp 

Cpp

Output:

The code shows how the two separate files are made and then linked using extern C to run the program in C++.

How to Compile and Run (Using Terminal or Replit)

Follow the given steps below to run the above program in the given example.

Step 1: Compile C Code

gcc -c c_code.c -o c_code.o

Step 2: Compile C++ Code

g++ -c main.cpp -o main.o

Step 3: Link Both Object Files

g++ main.o c_code.o -o output

Step 4: Run the Program

./output

3. Ensures C-Compatible Calling Conventions

Certain languages may use different calling conventions (how arguments are passed, which registers complement the algorithm, etc.). The extern 'C' tells the compiler to use C calling conventions, therefore, it makes the linking of C code easier.

Example:

Cpp

Output:

The code shows how the use of extern C in C++ ensures C-compatible calling conventions with the proper C linkage.

Basic Syntax of extern 'C' in C++

1. Declaring a Single Function

extern "C" void function_name();

2. Declaring Multiple Functions (Block Form)

extern "C" {
    void function1();
    int function2(int x);
}

Example:

Cpp

Output:

The code shows the use of the syntax of extern C in a C++ program.

How to Handle C Symbols When Linking from C++

The primary problem with linking C functions or variables within a C++ program is name mangling. C++ compilers modify function names to provide for function overloading, whereas C just uses the function name unchanged. This difference causes linkage errors when the programmer tries to use C functions within C++ code.

To handle this, "extern C" is used to tell the C++ compiler that C symbols should not be subject to name mangling.

Now, here are the following procedures to handle C symbols when linking from C++:

Step 1. Declare C functions in C++ using extern 'C' to prevent name mangling.

Step 2. Define the function in a separate C file (.c) without extern 'C'.

Step 3. Compile separately:

 gcc -c c_code.c -o c_code.o    (C file)
 g++ -c main.cpp -o main.o    (C++ file)

    Step 4. Link both files together:

    g++ main.o c_code.o -o output

    Step 5. Run the program: 

    ./output

    When to Use and When Not to Use extern 'C' in C++

    Now let's discuss when to use extern in order to enable interoperability between C and C++ and when to avoid it for compatibility issues with C++

    When to use extern 'C'

    1. The keyword 'extern 'C' helps to call C functions in C++, when contained in libraries such as <math.h> or <stdio.h>, so use it while calling C functions in C++.
    2. Also, extern 'C' can be utilized to expose C++ functions to C programs, and they are specifically useful for OS development, embedded system development, and mixed-language programs.
    3. By using extern 'C', you can establish a correct linkage to access global variables defined in C.
    4. You can use extern 'C' to prevent name mangling when passing C-compatible APIs in shared libraries(.so or .dll files).
    5. You can use extern 'C' to allow passing handling of function pointers from C++ to C APIs, such as pthread_create.
    6. You can use extern 'C' to allow a header file to be included by both C and C++ using #ifdef __cplusplus. 

    When not to use extern 'C'

    1. You should not use 'extern C' in a purely C++ code that has no C interaction.
    2. You should not use extern 'C' to prevent C++ function overloading. This option can be truly ineffective.
    3. The use of extern 'C' with C++ classes, templates, or namespaces, such constructs are not properly supported inside an extern 'C' block.
    4. You should not use extern 'C' for inline or static functions since they have internal linkage, and extern 'C' would have no effect.
    5. You cannot use the extern 'C' with C++ Standard Library features such as std::vector, std::string, or exceptions.

    Common Mistakes with extern 'C' in C++

    1. Forgetting to Apply extern 'C' When Declaring C Functions: It generally leads to linker errors caused by name mangling.
    2. Using extern 'C' on C++ Classes, Templates, or Overloaded Functions: extern 'C' is to be applied only on C-compatible functions and variables.
    3. Using extern 'C' Inside C File (.c): C does not allow extern 'C'; therefore, it can never be applied in C files.
    4. Not Properly Wrapping C Declarations in a Header File: Always use #ifdef __cplusplus to ensure compatibility.
    5. Forgetting to Link C and C++ Object Files: Needs to compile C and C++ in separate units and link them correctly afterward.
    6. Mixing static or inline with extern 'C': This has internal linkage, hence incompatible with extern 'C'.
    7. Putting extern 'C' in the Function Implementation instead of the Declaration: extern 'C' should be in the function declaration rather than definition.

    Best Practices of extern 'C' in C++

    1. extern 'C' should be only inside C++ code, and therefore never written in C code(.c), since C does not understand it.
    2. Header files must be used with #ifdef __cplusplus to define the function names such that they are compatible with the linkage requirements for C.
    3. When the extern 'C' is used, make those declarations, use it on declarations, never definitions.
    4. You must link C and C++ object files correctly.
    5. You must use extern 'C' to disallow any kind of name mangling of C global variables in any C++ code.
    6. Don't apply extern 'C' on C++ constructs, classes, templates, and overloaded functions.
    7. Using function pointers with extern 'C' allows for passing C++ functions into C libraries. 
    8. Always keep the extern 'C' blocks brief and to the point, and don't wrap or bind entire header files or other unnecessarily large sections.
    9. Properly comment on the code for maintainability purposes.
    10. Always check that your C and C++ codes link correctly without any name-mangling errors.

    Conclusion

    extern 'C' is a technique that enables the linking of C functions, global variables, and callbacks throughout C++ by avoiding name mangling. It establishes a C-compatible calling convention so programming experience with the different languages can be smooth. Proper use of extern 'C' avoids errors and ensures compatibility between C and C++. So, understanding the effects, uses, and best practices helps us to learn the best C++ programming practices.

    FAQs on What is the Effect of extern 'C' in C++?

    1. What will happen when I try to write a C function in C++ without extern C?

    In that case, there will be no linking, the linker process will fail because, upon compiling with C++, the compiler may apply an appropriate name-mangling algorithm.

    2. Can the extern 'C' be used in the presence of classes or function overloading?

    No, extern ‘C’ is only applicable to non-member C functions and global variables. It does not support C++ features like classes, namespaces, or overloading.

    3. Do I need extern 'C' to include standard C libraries like stdio.h?

    No, it is already implemented in the C++ headers. You can use <cstdio> directly in place of stdio.h.

    4. How do I put extern 'C' in use in a header file?

    You can wrap C function declarations within a #ifdef __cplusplus block to allow corresponding C functionality.

    5. Do I need extern 'C' for global variables?

    Yes, extern C enables C linkage, thus, you can use global variables such as extern ‘C'[int my_global_var;].

    About the Author

    Technical Research Analyst - Full Stack Development

    Kislay is a Technical Research Analyst and Full Stack Developer with expertise in crafting Mobile applications from inception to deployment. Proficient in Android development, IOS development, HTML, CSS, JavaScript, React, Angular, MySQL, and MongoDB, he’s committed to enhancing user experiences through intuitive websites and advanced mobile applications.

    Full Stack Developer Course Banner