在arm-gcc的环境下使用C/C++混合编程开发stm32
有的时候在用C进行一些面向对象的编程时,总需要考虑很多事情。尽管C也可以做面向对象编程,Linux内核就是这么做的。只是对于我们自己开发而言相对较麻烦,需要考虑很多事情,自己建立对象模型,再用函数指针实现对象的方法等,太过于繁琐。在需要实现面向对象编程时,C++会是一个不错的选择。
由于某些原因,我开发stm32程序的平台已经从MDK5转到了arm-gcc + vscode +openocd的组合模式。MDK5是支持C/C++混合编程的,而且设置方法非常简单,网络上教程一堆。
那么对于arm-gcc如何配置呢,下文细说。
首先需要使用stm32CubeMX生成一个基于Makefile的工程,生成后的工程目录如下:

ST的库虽然都是.c文件,但是都做了C/C++混合编程的处理,我们只需要修改Makefile即可。
①增加C++文件列表
效仿Makefile里C文件和汇编ASM文件列表的写法,添加C++的文件列表,往后所有.cpp文件都往此处添加。
②添加arm-g++编译器
使用arm-g++用来编译.cpp文件
③添加CPP全局宏定义
还是效仿C全局宏定义的写法,虽然可以直接使用C的,但是还是规范些好,万一以后要添加呢。
④添加CPP编译选项
还是一样,效仿C的写法,不过,在CPPFLAGS后再添加2个选项
-fno-rtti -fno-exceptions
-fno-rtt 表示不使用RTTI,即运行时类型识别,这意味着代码中不能使用typeid和dynamic_cast,但这可以使编译后的固件文件减小。
-fno-exceptions 表示不捕获程序异常,此选项也可以减小编译后的固件文件大小。
⑤添加关联信息
这一项是编译时生成关联信息,对链接有影响,还是直接拷贝C的实现。
⑥添加CPP文件列表
这里是利用makefile的语法从一堆源文件名生成对应的.o文件名,并且设置了.c .cpp .s文件的搜索路径。
⑦添加.cpp文件的编译规则
从上面的.c文件编译规则复制下来,将其改成CPP规则即可。
@和echo是我手动添加的,用于精简编译输出信息,与本文内容无关。
完成以上步骤后,Makefile就修改完成了,下面写一个Led.cpp测试一下
这里只放.h文件,c文件都是一些方法的实现,避免篇幅太长就不放了。
再看看main.cpp:
如果需要直接在原工程的main.c中编写C++程序,则需要将main.c修改为main.cpp。
这里我就修改了。
注意,我们在编写头文件的时候,最好加上extern “C”,用宏__cplusplus限制。因为C文件调用某个写在CPP的函数是会报错的,因为C++支持重载而C不支持。因此需要把一些可能会在C文件调用的函数的声明用extern “C”{}限制,否则在链接那一步会报错在C文件里调用的这个函数找不到。
在上面main.cpp中,SysTick_Callback()是我在定义的一个弱函数,他会在SysTick中断中被调用,这里就是因为在main.cpp中实现,原本的弱函数不会被替换,因此需要加上extern”C”{}限制才行。
另外,全局对象的构造函数是在程序还未进入main函数就执行了的,如果构造函数里有与硬件相关的代码就可能出错。所以尽量避免使用构造函数,除非你使用new 和 delete或者只使用局部变量。上面代码里可以看出我对于全局对象是使用静态方法Create进行初始化的。
编译顺利通过

最终程序烧录到stm32上也能正常运行,LED正常闪烁,这里我就不放效果图了。
最后附上我自己的Makefile完整版供参考

