【Keil】C/C++混合编程的简单方法

目录

前言:

一、在.c文件中添加C++代码

1、在cpp文件中定义C类型的接口函数

2、在C类型的接口函数内引用C++类型的封装好的函数接口API

3、在main.c文件中声明并调用C类型的接口函数

二、在.cpp文件中添加C代码

[三、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~](#三、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~)


前言:

C语言的高效性是其核心优势之一,可以直接操作硬件(如寄存器、内存地址),生成的机器码更接近底层,执行效率高,是Keil的标准语言。

C++性能接近C语言,但功能更加丰富,其三大特性------多态、继承、封装可以帮助开发者实现更加丰富的功能,尤其适合大型项目开发。

由于C语言和C++在编译规则、符号命名方式、函数调用约定等方面存在本质差异,导致两者之间无法直接调用,例如:C语言中的func函数在编译后会直接被保留为符号名func,但由于C++支持函数重载,允许多个函数使用相同名称,所以C++中的函数在编译后会自动生成对应当前函数的唯一符号名以便于区分,这就是两者不能直接互相调用的原因之一。

但是我们在keil中创建源文件时主函数都是main.c文件,那么如何在.c文件中使用C++环境下定义的函数和类呢?请看下文:

一、在.c文件中添加C++代码

在.c文件中添加C++代码主要包括三个步骤:

1、在cpp文件中定义C类型的接口函数

首先,我们需要创建一个独立于main.c之外的user_main.cpp文件(只要是.cpp文件就行,叫什么名字都可以),在文件中定义C类型的接口函数和C++的类实例,使得C和C++风格的代码在同一文件内相互可见。

user_main.cpp文件内容示例如下所示:

cpp 复制代码
#include "CSystem.h"		//包含C++实现类的头文件,以引出CSystem类
static CSystem MyCppClass;	//定义C++风格的CSystem类静态实例 m_theApp


#if defined(__cplusplus)	//如果当前处在C++环境
extern "C" {				//使用extren "C" { 定义C风格函数,使其在C名称空间内可见
#endif

void User_Init(void)		//定义C风格初始化接口函数
{
	MyCppClass.bInit();		//调用C++类实例m_theApp中实现的初始化函数API
}

void User_Task(void)		//定义C风格任务接口函数
{
	MyCppClass.vRun();		//调用C++类实例m_theApp中实现的任务函数API
}

#if defined(__cplusplus)
}							//使用 } 来结束定义C风格的函数
#endif

2、在C类型的接口函数内引用C++类型的封装好的函数接口API

详见上部分中的User_Init(void)函数和User_Task(void)函数内容,里面引用的就是C++的CSystem 类实例中的成员函数。

3、在main.c文件中声明并调用C类型的接口函数

main.c文件中的main函数,是项目代码的入口,在这里调用C++代码,最终实现C和C++两种风格编程语言的融合。main.c文件内容示例如下所示:

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

void SystemClock_Config(void);	//时钟初始化函数前置声明

void User_Init(void);	        //  C/C++混合编程接口初始化函数前置声明
void User_Task(void);			//  C/C++混合编程接口任务函数前置声明

int main(void)
{
  HAL_Init();			//HAL库初始化
  SystemClock_Config();	//系统时钟初始化
	
  MX_GPIO_Init();		//进行外设初始化
  
  User_Init();	        //C类型的混合编程接口初始化函数,在其中调用C++实现的初始化接口函数
  while (1)
  {
	User_Task();		//C类型的混合编程接口任务执行函数,循环调用C++类中实现的任务函数
  }
}

二、在.cpp文件中添加C代码

在C++中使用C比较简单,只需要在.cpp文件中使用 extren "C"{} 来将C类型的函数进行声明定义就可以,然后就可以在函数定义的文件范围内,正常调用C类型的函数,来实现具体功能,我们所熟知的中断回调函数就是一个很好的例子:

cpp 复制代码
extern "C" 
{
	void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
	{
		switch(GPIO_Pin)		
		{
			case GPIO_PIN_2:
			{
				INTIsReady = TRUE;	//更新数据就绪标志位
			}	break;
			default:
				break;
		}
	}
}

三、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~

相关推荐
云小逸3 小时前
C++ 第一阶段:对象、内存与生命周期
开发语言·c++
夜航海图3 小时前
S-57 数据解剖:把一个 ENC 文件拆给你看
c++
HRTOS3 小时前
HRTOS应用示例:信号量机制详解
c语言·人工智能·嵌入式硬件·51单片机
(Charon)3 小时前
【C++】网络缓冲区设计(三):Chain Buffer链式缓冲区、动态扩容与跨节点读写
服务器·c++
从零开始的嵌入式之旅4 小时前
day36
linux·c语言·经验分享·笔记·嵌入式硬件
HRTOS4 小时前
HRTOS应用示例:Mutex互斥锁机制详解
c语言·单片机·嵌入式硬件·51单片机
Sumerking5 小时前
llc_control.c 专项评审(v3 更新版)
c语言·开发语言·算法·obc
软行5 小时前
LeetCode 每日一题 3876. 构造奇偶一致的数组 II
c++·算法·leetcode
繁星蓝雨6 小时前
C++设计原理———重载(extern “C“的由来、顺序依赖、语义依赖、overload、名称修饰符、对象操作、运算符重载、新增运算符、枚举和布尔类型)
c语言·c++·extern c·overload·重载·语义依赖·顺序依赖
handler016 小时前
【Linux】虚拟地址空间解析
linux·运维·c++·线程·进程·虚拟地址空间·虚拟地址