1. 引言
由于本人就是属于对C++不那么熟悉的同学,所以下面会从我的视角来介绍上一篇文章遗留的问题,如果其中有错误或表述不当的地方,欢迎评论指正。
2. 代码解读
OE/samples/ucp_tutorial/目录下的结构如下:
在vp/code/07_single_rotate目录如下:
有个感觉即可,后面会细致的解读运行起一个VP示例所依赖的文件。
2.1 main.cpp
从main.cpp看过去,内容以及解读如下:
有两处拿出来解释下:
#include "rotate.h":该文件是一个自定义头文件,用于声明函数或类,代码中调用的 single_rotate() 在 rotate.h 中被声明,并在相应的 rotate.cpp 中被实现。
int32_t main(int32_t argc, char **argv):入口函数 main(),接收两个参数:
argc:命令行参数个数(包括程序本身)。
argv:存储命令行参数的字符串数组(char*)。
2.2 rotate.h
下面看一下头文件rotate.h,代码作用:声明 single_rotate() 函数,并防止头文件被重复包含。
来了解一下这段代码能防止头文件被重复包含。
#ifndef(如果未定义):检查宏 VP_CODE_07_ROTATE_IMAGE_PROCESS_H_ 是否已定义。
#define(定义宏):如果未定义,则定义该宏,并继续处理头文件的内容。
#endif 结束 #ifndef 逻辑块,确保头文件仅被包含一次。
这种方式称为 头文件保护(Header Guard),用于防止头文件的 重复包含,避免 编译错误。
还是有些不太理解?详细解释一下:
什么是头文件保护:在 C/C++ 语言中,头文件(.h)是用于声明变量、函数、类等的文件。为了防止头文件被 重复包含(multiple inclusion),通常使用 头文件保护(Header Guard),其基本结构是:
为什么要头文件保护:在大型 C++ 项目中,多个 .cpp 文件可能包含相同的头文件。例如:
A.h 头文件
B.h头文件
main.cpp中
当 main.cpp 被编译时,它会展开 #include:在A.h中直接包含void foo();,B.h 也包含 A.h,再次引入void foo();这会导致重复声明,如果没有 头文件保护,编译器可能会报错:
当使用了上面#ifndef / #define / #endif,就可以避免这个问题,原理如下:
第一次 包含 A.h 时:
A_H 未定义,#ifndef A_H 成立 → 继续执行
进入 #define A_H 代码块,定义 A_H
头文件 A.h 正常加载
第二次 再次包含 A.h:
A_H 已定义,#ifndef A_H 失败 → 直接#endif,跳过整个头文件
编译器在处理头文件时会进行优化,所以头文件保护不会影响性能,为了避免 重复包含头文件 导致的编译错误,提高代码可维护性,推荐大家使用头文件保护。
最后,#ifndef 保护多个头文件需要不同的宏名,因为宏名重复,也可能导致错误,建议使用 文件名相关的宏 方便记忆排查。
2.3 log_util.h
2.4 rotate.cpp
想了解VP示例中CMakeLists.txt的嵌套以及运行逻辑,可见文章:【J6】工具链VP示例中Cmakelists解读。
2.6 build.sh
该 Bash 脚本 用于 构建 aarch64(ARM64)或 x86(PC 端)架构的项目,并支持 自动检测 gcc 版本,确保编译环境正确。
getopt 会返回一个规范化的、已排序的选项和参数字符串,存储在 GETOPT_ARGS 变量中。例如,输入:
则 GETOPT_ARGS 可能会被解析成:
希望把build.sh脚本运行起来:
到这儿,项目构建编译就完成了。
3. 程序执行
项目构建完成后,会在vp/vp_samples下准备好程序可执行的相关依赖文件
运行vp_samples/script_x86/07_single_rotate/run_single_rotate.sh脚本即可。
至此,程序完成运行。

