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:
- Function Overloading (same function name with different parameters).
- Namespaces (functions with the same name in different namespaces).
- Member Functions (functions inside a class).
To distinguish between these functions, C++ uses mangling that adds extra bits of information into the name.
Example:
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:
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
File 2: main.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:
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:
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'
- 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++.
- 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.
- By using extern 'C', you can establish a correct linkage to access global variables defined in C.
- You can use extern 'C' to prevent name mangling when passing C-compatible APIs in shared libraries(.so or .dll files).
- You can use extern 'C' to allow passing handling of function pointers from C++ to C APIs, such as pthread_create.
- 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'
- You should not use 'extern C' in a purely C++ code that has no C interaction.
- You should not use extern 'C' to prevent C++ function overloading. This option can be truly ineffective.
- The use of extern 'C' with C++ classes, templates, or namespaces, such constructs are not properly supported inside an extern 'C' block.
- You should not use extern 'C' for inline or static functions since they have internal linkage, and extern 'C' would have no effect.
- 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++
- Forgetting to Apply extern 'C' When Declaring C Functions: It generally leads to linker errors caused by name mangling.
- Using extern 'C' on C++ Classes, Templates, or Overloaded Functions: extern 'C' is to be applied only on C-compatible functions and variables.
- Using extern 'C' Inside C File (.c): C does not allow extern 'C'; therefore, it can never be applied in C files.
- Not Properly Wrapping C Declarations in a Header File: Always use #ifdef __cplusplus to ensure compatibility.
- Forgetting to Link C and C++ Object Files: Needs to compile C and C++ in separate units and link them correctly afterward.
- Mixing static or inline with extern 'C': This has internal linkage, hence incompatible with extern 'C'.
- 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++
- extern 'C' should be only inside C++ code, and therefore never written in C code(.c), since C does not understand it.
- Header files must be used with #ifdef __cplusplus to define the function names such that they are compatible with the linkage requirements for C.
- When the extern 'C' is used, make those declarations, use it on declarations, never definitions.
- You must link C and C++ object files correctly.
- You must use extern 'C' to disallow any kind of name mangling of C global variables in any C++ code.
- Don't apply extern 'C' on C++ constructs, classes, templates, and overloaded functions.
- Using function pointers with extern 'C' allows for passing C++ functions into C libraries.
- 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.
- Properly comment on the code for maintainability purposes.
- 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;].