C 和 C++ 之间进行混合编程时,最大的障碍之一是名称修饰(name mangling)。C++ 编译器会对函数名进行编码(mangling),以支持函数重载等特性,而 C 语言不会。这就导致一个 C++ 编译的函数不能被 C 代码直接链接调用,反之亦然。extern C 就是解决这个问题。

1、extern "C" 简介

extern "C" 是一种链接说明(linkage specification),用于告诉 C++ 编译器按照 C 语言的方式来处理函数的名称(不进行名称修饰),从而保证 C 和 C++ 代码可以互操作

#ifdef __cplusplus
extern "C" {
#endif

void c_function();  // 声明一个可以被 C 和 C++ 共享的函数

#ifdef __cplusplus
}
#endif

或者针对单个函数:

extern "C" void c_function();

2、使用场景

1)C++ 调用 C 代码

当想从 C++ 中调用用 C 编写的库函数时,需要使用 extern "C" 来避免 C++ 编译器进行名称修饰。

// some_c_library.h (C语言头文件)
#ifndef SOME_C_LIBRARY_H
#define SOME_C_LIBRARY_H

void say_hello();

#endif

C语言实现文件:

// some_c_library.c (C语言实现文件)
#include <stdio.h>

void say_hello() {
    printf("Hello from C library!\n");
}

C++ 调用示例:

// C++ 代码
extern "C" {
    #include "some_c_library.h"
}

2)C 调用 C++ 代码

如想让 C 调用 C++ 函数,需使用 extern "C" 来导出 C 兼容的函数名。

C 语言函数定义在 c_code.c

// c_code.c
#include <stdio.h>

void my_function() {
    printf("Hello from C function!\n");
}

在 C++ 文件中这样声明并调用它

// main.cpp
#include <iostream>

extern "C" void my_function();  // 用 C 链接方式声明

int main() {
    std::cout << "Calling C function from C++...\n";
    my_function();  // 调用 C 函数
    return 0;
}

注意extern "C" 不能用于类或类的成员函数,只能用于普通函数、全局变量和头文件声明。无法用于函数重载,因为 C 不支持函数重载。

3)常见写法模板

在头文件中使用。

#ifdef __cplusplus
extern "C" {
#endif

void my_api();  // C 风格函数接口

#ifdef __cplusplus
}
#endif