Complete Guide to C/C++ Mixed Programming

πŸ‘‡ Follow our official account and select Star, to receive the latest content daily

Introduction

This article demonstrates the core technologies of C/C++ mixed programming through practical projects. It covers essential knowledge points from the basic extern "C" linkage specification to the complete compilation process, including name mangling, header file design, and CMake build. By combining practical cases in the Windows MSVC environment, it helps readers master the essence of collaboration between the two languages and solve compatibility issues in real projects.

Complete Guide to C/C++ Mixed Programming

Basic Concepts

What is C/C++ Mixed Programming?

Writing code in both C and C++ languages within the same project, allowing them to call each other.

Why is Mixed Programming Needed?

  • Legacy Code: Utilizing existing C language libraries
  • Performance Considerations: C language performs better in certain scenarios
  • Library Compatibility: Many low-level libraries are written in C
  • Team Skills: Team members have varying familiarity with different languages

Core Technical Points

1. Name Mangling Issues

Cause of the Problem:

  • C Compiler: Function name <span>add</span> β†’ Symbol name <span>add</span>
  • C++ Compiler: Function name <span>add</span> β†’ Symbol name <span>?add@@YAHHH@Z</span> (supports function overloading)

Solution: Use <span>extern "C"</span> to inform the C++ compiler to use C linkage conventions.

2. Usage of extern “C”

// Method 1: Single function
extern "C" int c_function(int a, int b);

// Method 2: Multiple functions
extern "C" {
    int func1(int a);
    int func2(int b);
}

// Method 3: Conditional compilation (recommended)
#ifdef __cplusplus
extern "C" {
#endif

int c_function(int a, int b);

#ifdef __cplusplus
}
#endif

3. Header File Design Patterns

Standard Mixed Programming Header File Template:

#ifndef HEADER_NAME_H
#define HEADER_NAME_H

#ifdef __cplusplus
extern "C" {
#endif

// C function declarations
int c_function(int a, int b);
void c_procedure(const char* str);

#ifdef __cplusplus
}
#endif

// C++ specific section
#ifdef __cplusplus
class CppClass {
public:
    int cpp_method(int a, int b);
};

int cpp_function(int a, int b);
#endif

#endif // HEADER_NAME_H

4. Compiler Selection Mechanism

CMake Automatic Selection:

  • <span>.c</span> files β†’ C compiler
  • <span>.cpp</span>, <span>.cxx</span>, <span>.cc</span> files β†’ C++ compiler

Compilation Parameter Confirmation:

  • Windows MSVC:<span>/TC</span> (C mode), <span>/TP</span> (C++ mode)
  • Linux GCC:<span>gcc</span> (C compiler), <span>g++</span> (C++ compiler)

Practical Examples

Project Structure

project/
β”œβ”€β”€ CMakeLists.txt
β”œβ”€β”€ main.cpp          (C++ main program)
β”œβ”€β”€ math_c.c          (C implementation)
β”œβ”€β”€ math_cpp.cpp      (C++ implementation)
└── math_functions.h  (mixed header file)

1. CMakeLists.txt

cmake_minimum_required(VERSION 3.10.0)
project(
  mixed_programming
  VERSION 1.0.0
  LANGUAGES C CXX)

# Add executable file
add_executable(${PROJECT_NAME} 
    main.cpp 
    math_c.c 
    math_cpp.cpp
)

# Optional: Set C++ standard
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17)

2. Header File (math_functions.h)

#ifndef MATH_FUNCTIONS_H
#define MATH_FUNCTIONS_H

#ifdef __cplusplus
extern "C" {
#endif

// C function declarations
int add_c(int a, int b);
int multiply_c(int a, int b);
void print_result_c(const char* operation, int result);

#ifdef __cplusplus
}
#endif

// C++ function declarations
#ifdef __cplusplus
#include <string>

int add_cpp(int a, int b);
int multiply_cpp(int a, int b);
void print_result_cpp(const std::string& operation, int result);

// C++ class
class Calculator {
private:
    std::string name;
    
public:
    Calculator(const std::string& calc_name);
    int calculate(int a, int b, char op);
    void show_history() const;
};
#endif

#endif // MATH_FUNCTIONS_H

3. C Language Implementation (math_c.c)

#include <stdio.h>
#include "math_functions.h"

int add_c(int a, int b) {
    printf("[C Function] Calculation: %d + %d\n", a, b);
    return a + b;
}

int multiply_c(int a, int b) {
    printf("[C Function] Calculation: %d * %d\n", a, b);
    return a * b;
}

void print_result_c(const char* operation, int result) {
    printf("[C Function] The result of %s is: %d\n", operation, result);
}

4. C++ Language Implementation (math_cpp.cpp)

#include <iostream>
#include <vector>
#include "math_functions.h"

// C++ function implementation
int add_cpp(int a, int b) {
    std::cout << "[C++ Function] Calculation: " << a << " + " << b << std::endl;
    return a + b;
}

int multiply_cpp(int a, int b) {
    std::cout << "[C++ Function] Calculation: " << a << " * " << b << std::endl;
    return a * b;
}

void print_result_cpp(const std::string& operation, int result) {
    std::cout << "[C++ Function] " << operation << " The result is: " << result << std::endl;
}

// C++ class implementation
Calculator::Calculator(const std::string& calc_name) : name(calc_name) {
    std::cout << "Creating calculator: " << name << std::endl;
}

int Calculator::calculate(int a, int b, char op) {
    switch(op) {
        case '+': return add_cpp(a, b);
        case '*': return multiply_cpp(a, b);
        default: return 0;
    }
}

void Calculator::show_history() const {
    std::cout << "Calculator " << name << " history" << std::endl;
}

5. Main Program (main.cpp)

#include <iostream>
#include "math_functions.h"

int main() {
    std::cout << "=== C/C++ Mixed Programming Example ===" << std::endl;
    
    // Call C functions
    std::cout << "\n--- Calling C Functions ---" << std::endl;
    int result_c1 = add_c(10, 20);
    int result_c2 = multiply_c(5, 6);
    print_result_c("Addition", result_c1);
    print_result_c("Multiplication", result_c2);
    
    // Call C++ functions
    std::cout << "\n--- Calling C++ Functions ---" << std::endl;
    int result_cpp1 = add_cpp(15, 25);
    int result_cpp2 = multiply_cpp(7, 8);
    print_result_cpp("Addition", result_cpp1);
    print_result_cpp("Multiplication", result_cpp2);
    
    // Use C++ class
    std::cout << "\n--- Using C++ Class ---" << std::endl;
    Calculator calc("Mixed Calculator");
    int result_class = calc.calculate(12, 8, '+');
    calc.show_history();
    
    // Demonstrate mutual calls
    std::cout << "\n--- Mixed Calls ---" << std::endl;
    std::cout << "C++ calls C function result: " << add_c(100, 200) << std::endl;
    
    return 0;
}

Compilation and Linking Process

Complete Compilation Process

1. Configuration Stage (cmake)
   β”œβ”€β”€ Read CMakeLists.txt
   β”œβ”€β”€ Detect C/C++ compilers
   β”œβ”€β”€ Generate build files (.vcxproj/.sln or Makefile)
   └── Save configuration to CMakeCache.txt

2. Build Stage (cmake --build)
   β”œβ”€β”€ Preprocessing (Preprocessing)
   β”‚   β”œβ”€β”€ main.cpp + headers β†’ main.i
   β”‚   β”œβ”€β”€ math_c.c + headers β†’ math_c.i
   β”‚   └── math_cpp.cpp + headers β†’ math_cpp.i
   β”‚   (Note: After preprocessing, header files disappear, content merges into .i files)
   β”‚
   β”œβ”€β”€ Compilation (Compilation)
   β”‚   β”œβ”€β”€ main.i β†’ main.s (assembly code)
   β”‚   β”œβ”€β”€ math_c.i β†’ math_c.s (assembly code)
   β”‚   └── math_cpp.i β†’ math_cpp.s (assembly code)
   β”‚
   β”œβ”€β”€ Assembly (Assembly)
   β”‚   β”œβ”€β”€ main.s β†’ main.obj (machine code)
   β”‚   β”œβ”€β”€ math_c.s β†’ math_c.obj (machine code)
   β”‚   └── math_cpp.s β†’ math_cpp.obj (machine code)
   β”‚
   └── Linking (Linking)
       β”œβ”€β”€ Symbol resolution: matching function calls and definitions
       β”œβ”€β”€ Address relocation: determining final memory addresses
       β”œβ”€β”€ Library linking: linking system libraries and runtime libraries
       └── Generate executable file: mixed_programming.exe

Key Compilation Parameters

Windows (MSVC):

# C++ file compilation
cl.exe /c /TP main.cpp math_cpp.cpp

# C file compilation  
cl.exe /c /TC math_c.c

# Linking
link.exe main.obj math_c.obj math_cpp.obj /OUT:program.exe

Linux (GCC):

# C++ file compilation
g++ -c main.cpp math_cpp.cpp

# C file compilation
gcc -c math_c.c

# Linking
g++ main.o math_c.o math_cpp.o -o program

Common Issues and Solutions

1. Linking Error: unresolved external symbol

Error Phenomenon:

error LNK2019: unresolved external symbol "int __cdecl add_c(int,int)"

Cause: Missing <span>extern "C"</span> declaration

Solution:

// Add in header file
extern "C" int add_c(int a, int b);

2. Redefinition Error

Error Phenomenon:

error LNK2005: add_c already defined

Cause: Function definitions included in the header file

Solution:

  • Only declarations in header files, no definitions
  • Use <span>inline</span> keyword (only for simple functions)
  • Add header file protection

3. C++ Features Error in C Code

Error Phenomenon:

// In .c file
std::cout << "Hello"; // Error! C does not support C++ syntax

Solution:

  • Use only C syntax in C files
  • C++ features only in .cpp files

4. Header File Duplicate Inclusion

Solution: Use header file protection

#ifndef HEADER_NAME_H
#define HEADER_NAME_H
// Header file content
#endif

Best Practices

1. Project Organization

project/
β”œβ”€β”€ include/          # Public header files
β”‚   └── api.h
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ c_module/     # C language module
β”‚   β”‚   β”œβ”€β”€ module.c
β”‚   β”‚   └── module.h
β”‚   β”œβ”€β”€ cpp_module/   # C++ language module  
β”‚   β”‚   β”œβ”€β”€ module.cpp
β”‚   β”‚   └── module.hpp
β”‚   └── main.cpp
β”œβ”€β”€ CMakeLists.txt
└── README.md

2. Naming Conventions

// C functions: use underscore naming
int calculate_sum_c(int a, int b);

// C++ functions: use camel case naming
int calculateSumCpp(int a, int b);

// File naming
module.c    // C implementation
module.cpp  // C++ implementation  
module.h    // C/C++ compatible header file
module.hpp  // Pure C++ header file

3. Error Handling

// C style error handling
extern "C" {
    typedef enum {
        SUCCESS = 0,
        ERROR_INVALID_PARAM = -1,
        ERROR_MEMORY = -2
    } ErrorCode;
    
    ErrorCode process_data_c(const char* data, int* result);
}

// C++ style error handling
#ifdef __cplusplus
#include <stdexcept>

class ProcessingException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Processing failed";
    }
};

void processDataCpp(const std::string& data);
#endif

4. Memory Management

// C style memory management
extern "C" {
    char* allocate_buffer_c(size_t size);
    void free_buffer_c(char* buffer);
}

// C++ style memory management
#ifdef __cplusplus
#include <memory>

std::unique_ptr<char[]> allocateBufferCpp(size_t size);
#endif

5. Build Script Optimization

# Set compilation options
if(MSVC)
    # Windows specific settings
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
else()
    # Linux/Unix specific settings
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
endif()

# Handle C and C++ files separately
set_source_files_properties(
    ${C_SOURCES} 
    PROPERTIES LANGUAGE C
)

set_source_files_properties(
    ${CXX_SOURCES} 
    PROPERTIES LANGUAGE CXX
)

Conclusion

The key to C/C++ mixed programming lies in:

  1. Understanding Compiler Differences: C and C++ have different compilation and linking rules
  2. **Correctly Using extern “C”**: Resolving name mangling issues
  3. Well-Designed Header Files: Using conditional compilation to support both languages
  4. Following Best Practices: Project organization, naming conventions, error handling

By mastering these knowledge points, you can successfully implement C/C++ mixed programming in your projects, fully leveraging the advantages of both languages.

β€”THE ENDβ€”

For the latest updates and experiences with large model agents, please follow our mini-programπŸ‘‡πŸ‘‡

Complete Guide to C/C++ Mixed Programming

Reply “Join Group” in the official account to join the mutual assistance group, and you can get the complete keyword list in the 【menu】 of the official account (updated irregularly).

Complete Guide to C/C++ Mixed Programming

This article is for academic sharing only. If there is any infringement, please contact us for deletion. Thank you very much!

Leave a Comment