【C++ 语言】 C 与 C++ 兼容 ( extern "C" )(三)

简介: 【C++ 语言】 C 与 C++ 兼容 ( extern "C" )(三)

7. 总结 :


① 编译结果对比 : C 语言 add 方法编译后的符号是 add , C++ 编译后的符号是 _Z3addii , 显然二者不能互相调用 , 因此一旦在 C++ 中调用 add , 就会出现上述无法解析外部符号错误 ;

② 兼容 : 如果在 C++ 文件中调用 C 语言库 , 需要做兼容处理 ;

③ 示例 : 在 Android 中的 NDK 接口是 C++ 语言的 , 但是调用的库 如 OpenSL ES , FFMPEG 等都是 C语言的库 , 因此这里就需要用到 C 与 C++ 的兼容 ;

④ 兼容方法 : 使用 extern “C”{} 指定让大括号中的内容 以 C 语言的方式进行编译 ; 这样才能在 C++ 中找到对应的 C 语言中的函数 ; 如下示例 :

extern "C"{
  #include "c_extern.c"
}



编译过程 : 预处理 -> 编译 -> 汇编 -> 链接;

1. 编译预处理 : 产生 .i 后缀的预处理文件;

2. 编译操作 : 产生 .s 后缀的汇编文件;

3. 汇编操作 : 产生 .o 后缀的机器码二进制文件;

4. 链接操作 : 产生可执行文件 ;




extern “C” 在头文件中的标准用法


extern “C” 用法 :


1. 在引用处使用 : extern “C” {} 可以写在 引用 头文件的位置 , 如下 :

// 001_CMake_1.cpp: 定义应用程序的入口点。
//
#include "001_CMake_1.h"
extern "C" {
  #include "c_extern.h"
}
using namespace std;
int main()
{
  cout << "Hello CMake。" << endl;
  //调用 c_extern.h 头文件中定义的方法
  //该方法定义在了 C 语言文件中
  add(1, 2);
  return 0;
}


2. 在头文件中定义 : extern “C” {} 也可以写在 头文件 中 , 一般情况下我们编写的 C 代码需要同时兼容 C 和 C++ , 因此 C 语言的头文件都进行如下定义 :

① __cplusplus 宏 : 该宏定义在 C++ 编译器中 , 如果是 C 语言编译器 , 就不会定义该宏 ;

② 使用效果 : 如果在 C++ 编译环境中 , extern “C” { 和 } 生效 , 在 C 语言编译环境中 , 不生效 ;

#pragma once


//兼容 C 与 C ++ 语言 , 在 C++ 中也可以编译 C 语言程序
// __cplusplus 是编译器中定义的 宏 
//如果编译的是 C++ 代码 , 定义了__cplusplus 宏 ,  #ifdef __cplusplus 宏会生效
//这一组判定 extern "C" { 声明 , 是否生效 , 如果在 C++ 环境中生效 , C 语言环境中不生效
#ifdef __cplusplus
extern "C" {
#endif
  //任意定义一个方法 , 该方法有若干个参数和返回值
  int add(int a, int b);
//这一组判定 } 声明 , 是否生效 , 如果在 C++ 环境中生效 , C 语言环境中不生效
#ifdef __cplusplus
}
#endif


注意上述兼容二选一 , 不能同时使用 , 否则会报错 ;




最终的 C / C ++ 兼容 代码


最终的 C / C ++ 兼容 代码 :


1.程序结构 :

image.png

2.顶层 CMakeLists.txt : 配置多个项目 ;

# CMakeList.txt: 顶层 CMake 项目文件,在此处执行全局配置
# 并包含子项目。
#
cmake_minimum_required (VERSION 3.8)
project ("001_CMake_1")
# 包含子项目。
add_subdirectory ("001_CMake_1")


3.项目 CMakeLists.txt : 配置单个项目中的多个源文件 ;

# CMakeList.txt: 001_CMake_1 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
cmake_minimum_required (VERSION 3.8)
# 将源代码添加到此项目的可执行文件。
add_executable (001_CMake_1 "001_CMake_1.cpp" "001_CMake_1.h" "c_extern.c" "c_extern.h")
# TODO: 如有需要,请添加测试并安装目标。


4.c_extern.h :

#pragma once
//兼容 C 与 C ++ 语言 , 在 C++ 中也可以编译 C 语言程序
// __cplusplus 是编译器中定义的 宏 
//如果编译的是 C++ 代码 , 定义了__cplusplus 宏 ,  #ifdef __cplusplus 宏会生效
//这一组判定 extern "C" { 声明 , 是否生效 , 如果在 C++ 环境中生效 , C 语言环境中不生效
#ifdef __cplusplus
extern "C" {
#endif
  //任意定义一个方法 , 该方法有若干个参数和返回值
  int add(int a, int b);
//这一组判定 } 声明 , 是否生效 , 如果在 C++ 环境中生效 , C 语言环境中不生效
#ifdef __cplusplus
}
#endif


5.c_extern.c :

#include "c_extern.h"
//实现的头文件中的方法, 用于测试 C 与 C++ 兼容问题
int add(int a, int b)
{
  return 0;
}



7.001_CMake_1.h :

// 001_CMake_1.h: 标准系统包含文件的包含文件
// 或项目特定的包含文件。
#pragma once
#include <iostream>
// TODO: 在此处引用程序需要的其他标头。


8.001_CMake_1.cpp :

// 001_CMake_1.cpp: 定义应用程序的入口点。
//
#include "001_CMake_1.h"
#include "c_extern.h"
using namespace std;
int main()
{
  cout << "Hello CMake。" << endl;
  //调用 c_extern.h 头文件中定义的方法
  //该方法定义在了 C 语言文件中
  add(1, 2);
  return 0;


9.运行结果 :

image.png

目录
相关文章
|
2月前
|
存储 编译器 C语言
详解C/C++中的static和extern
本文详解了C/C++中`static`和`extern`关键字的用法和区别,通过具体代码示例说明了在不同情境下如何正确使用这两个关键字,以及`extern "C"`在C++中用于兼容C语言库的特殊作用。
详解C/C++中的static和extern
|
3月前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
74 2
|
3月前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
79 0
|
1月前
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
34 5
|
1月前
|
存储 编译器 C语言
深入计算机语言之C++:类与对象(上)
深入计算机语言之C++:类与对象(上)
|
1月前
|
存储 分布式计算 编译器
深入计算机语言之C++:C到C++的过度-2
深入计算机语言之C++:C到C++的过度-2
|
1月前
|
编译器 Linux C语言
深入计算机语言之C++:C到C++的过度-1
深入计算机语言之C++:C到C++的过度-1
|
2月前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
20 0
|
3月前
|
编译器 C++ 容器
C++语言的基本语法
想掌握一门编程语言,第一步就是需要熟悉基本的环境,然后就是最重要的语法知识。 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。 完整关键字
|
4月前
|
前端开发 编译器 程序员
协程问题之为什么 C++20 的协程代码比其他语言的协程 demo 长很多如何解决
协程问题之为什么 C++20 的协程代码比其他语言的协程 demo 长很多如何解决