extern “C“

extern "C",经常使用的东西,但是在不同场景下含义有一些区别:

extern "C" 在 C 调用 C++ 和 C++ 调用 C 的场景下,确实有不同的含义,尽管它们的核心概念都是告诉编译器如何处理符号(即函数名)的方式。

1. C 调用 C++:

在这种情况下,C 代码想要调用 C++ 的函数。由于 C++ 使用名称修饰(name mangling)来支持函数重载,C 编译器无法识别 C++ 中修饰过的名称。为了让 C 代码能够调用 C++ 函数,我们需要告诉 C++ 编译器 按照 C 的调用约定和符号规则来导出函数,这样 C 编译器就能识别并调用它。

cpp 复制代码
// C++ 函数
extern "C" void foo() {
    // C++ 实现
}
  • extern "C" 在这里的作用是告诉 C++ 编译器按照 C 的链接规则来导出函数。

  • C 代码调用时,会按 C 的规则来查找 foo 函数,而 C++ 会确保 foo 函数没有被名称修饰,C 编译器就能正确识别它。

2. C++ 调用 C:

在这种情况下,C++ 代码想要调用 C 函数。C 编译器不会做名称修饰,因此 C++ 编译器需要告知编译器使用 C 的链接规则,防止它对符号进行修饰,使得 C++ 代码能够正确地链接到 C 函数。

cpp 复制代码
// C++ 代码
extern "C" {
    void bar();  // 声明 C 中的函数
}

void call_c() {
    bar();  // 调用 C 函数
}
  • extern "C" 在这里的作用是告诉 C++ 编译器 不做名称修饰,而是按照 C ABI(应用二进制接口)来导出符号,这样 C++ 编译器就不会修改函数名,让 C++ 代码能够正确调用 C 函数。

主要区别:

  • C 调用 C++: C 编译器无法处理 C++ 的名称修饰,使用 extern "C" 是为了告诉 C++ 编译器按照 C 的链接规范导出符号,确保 C 可以调用。

  • C++ 调用 C: C++ 编译器需要遵循 C 的链接规范,防止 C++ 对函数名做修饰,使用 extern "C" 是为了让 C++ 编译器遵循 C 的 ABI 规则来查找和链接 C 函数。

结论:

extern "C" 在这两种场景下的作用是相同的------告诉编译器按照 C 的符号规则来处理符号。在 C++ 调用 C 时,extern "C" 确保符号名称不会被修饰在 C 调用 C++ 时,extern "C" 确保 C++ 的符号名称符合 C 的规则以便 C 编译器可以识别并链接

C调用C++的例子:

(1)C++ 实现文件(player.cpp

cpp 复制代码
#include "player_c_api.h"
#include <iostream>

class Player {
public:
    void start() {
        std::cout << "Player start\n";
    }
};

extern "C" {

struct PlayerHandle {
    Player* impl;
};

PlayerHandle* player_create() {
    PlayerHandle* h = new PlayerHandle;
    h->impl = new Player();
    return h;
}

void player_start(PlayerHandle* h) {
    if (h && h->impl) {
        h->impl->start();
    }
}

void player_destroy(PlayerHandle* h) {
    if (h) {
        delete h->impl;
        delete h;
    }
}

}

(2)C 头文件(player_c_api.h

cpp 复制代码
#ifndef PLAYER_C_API_H
#define PLAYER_C_API_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct PlayerHandle PlayerHandle;

PlayerHandle* player_create(void);
void player_start(PlayerHandle* handle);
void player_destroy(PlayerHandle* handle);

#ifdef __cplusplus
}
#endif

#endif

(3)C 调用方(main.c

cpp 复制代码
#include "player_c_api.h"

int main() {
    PlayerHandle* p = player_create();
    player_start(p);
    player_destroy(p);
    return 0;
}
相关推荐
2601_949146538 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
知南x10 小时前
【Ascend C系列课程(高级)】(1) 算子调试+调优
c语言·开发语言
2的n次方_12 小时前
Runtime 执行提交机制:NPU 硬件队列的管理与任务原子化下发
c语言·开发语言
凡人叶枫13 小时前
C++中智能指针详解(Linux实战版)| 彻底解决内存泄漏,新手也能吃透
java·linux·c语言·开发语言·c++·嵌入式开发
凡人叶枫14 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
傻乐u兔15 小时前
C语言进阶————指针3
c语言·开发语言
CodeSheep程序羊16 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展
I'mChloe17 小时前
PTO-ISA 深度解析:PyPTO 范式生成的底层指令集与 NPU 算子执行的硬件映射
c语言·开发语言
2的n次方_17 小时前
Runtime 内存管理深化:推理批处理下的内存复用与生命周期精细控制
c语言·网络·架构
嵌入小生00717 小时前
标准IO---核心函数接口延续(嵌入式Linux)
c语言·vscode·vim·嵌入式·小白·标准io·函数接口