第五章 · Ubuntu 环境下编程
做机器人最常用的两门语言就是 C++ 和 Python,它们也常年排在编程语言流行度排行榜的前列。这一章先不急着进 ROS 2,而是在 Ubuntu 终端里把这两门语言的 Hello World 各跑一遍,看看 Linux 下写程序、跑程序和 Windows 有什么不同;最后再解释一句:Python 写起来那么爽,为什么跑起来偏慢。
5.1 为什么先看 C++ 和 Python
这两门语言在机器人开发里几乎是绕不开的:底层驱动、实时性要求高的模块用 C++,上层逻辑、脚本和快速验证用 Python。而且两门都学过——C++ 是课上教的,Python 语法极其简单,不需要从头再讲一遍。
真正值得对比的是另一件事:同一个 Hello World,在 Ubuntu 下从“写”到“跑”要走哪些步骤。先把这件事看清楚,后面写 ROS 2 节点时才不会对着编译错误发懵。
5.2 在 Linux 里怎么打开代码
在 Linux 里写代码,不少人的方式是直接拿记事本类工具开干。Ubuntu 自带 gedit,一条命令就能新建并打开文件:
gedit hello_ros2.cpp它的好处是不用打开 IDE,全程可以待在命令行终端里,改完代码、关掉窗口、接着敲命令。Linux 里还有 Vim 这种极其强大的编辑器,但上手难度太高,初学阶段先不碰。以后正经写项目,大概率还是在 VS Code 里完成;这一章先用最原始的方式,把“程序是怎么运行起来的”这件事弄明白。
先建好 d2lros2 目录,再在里面建一个 chapt1 目录,后面的 C++ 和 Python 代码都放在这里。
5.3 第一个 C++ 程序
5.3.1 写代码
在 d2lros2/chapt1 下,用 gedit 创建并打开 hello_ros2.cpp,输入下面六行:
#include <iostream>
using namespace std;
int main(){
cout<<"Hello ROS 2!"<<endl;
return 0;
}保存代码,关闭 gedit。
5.3.2 装编译器
C++ 代码必须经过编译构建之后才能运行,而 Linux 下负责编译 C++ 的是 g++。它默认没有安装,需要手动装一下:
sudo apt install g++5.3.3 编译与运行
装好之后,在终端里对刚才的源文件执行编译:
g++ hello_ros2.cpp再用 ls 看一眼当前目录,应该会多出一个叫 a.out 的文件。这个文件就是编译出来的可执行程序,直接运行它:
./a.out终端会输出 Hello ROS 2!。到这里,第一个 C++ 程序就跑通了。
Windows 的 .exe 与 Linux 的 .out
这里能看出一个明显区别:Windows 下编译出来的可执行文件是 .exe,双击就能运行;Linux 下的可执行文件是 .out(a.out 就是默认输出名),运行时必须在终端里带上 ./ 指明“运行当前目录下的这个文件”。
另外,第一次从写代码到跑起来其实敲了三行命令:装编译器、编译、运行。记住这个“三步走”,下面和 Python 对比时会用到。
5.4 第一个 Python 程序
Python 这边就简单多了。同样用 gedit 新建文件:
gedit hello_ros2.py输入一行,保存并关闭:
print("Hello ROS 2!")然后直接在终端里运行:
python3 hello_ros2.pyPython 不需要先编译成可执行文件,也不需要额外装编译器,一行 python3 命令就能把源码跑起来。
5.5 C++ 与 Python 的直观对比
把上面两段流程摆在一起看:

图:Python 与 C++ 的对比
| 对比项 | C++ | Python |
|---|---|---|
| 写一个 Hello World | 6 行(头文件、命名空间、main、输出、return、花括号) | 1 行 |
| 从零到跑起来 | 3 步:装编译器、编译、运行 | 1 步:python3 直接运行 |
| 语法风格 | 需要声明类型、写分号、管命名空间 | 接近自然语言 |
| 执行方式 | 编译执行 | 解释执行 |
| 运行速度 | 快 | 慢 |
从这张表看,Python 至少有三处占优:
- 程序更简单。C++ 要 6 行才能搞定的程序,Python 只要 1 行。
- 命令行里运行更简单。C++ 最短要三行命令,Python 只要一行。
- 语法更接近自然语言,读起来几乎就是一句英文。
于是有人会问:那 Python 岂不是大获全胜?
并不是。Python 确实好用,但它慢。这个“慢”不是语法问题,而是执行方式决定的:C++ 是编译执行,Python 是解释执行。接下来把这两个词拆开讲清楚。
5.6 编译执行与解释执行
5.6.1 “编译型语言”“解释型语言”只是印象
用“解释型语言 / 编译型语言”来给语言分类,本身就不太准确。设计语言的人并不会先定好“我要造一门编译型语言”,而是在实现过程中发现某种方式更合适就采用了它。一门语言最终被贴上“XX 型”的标签,更多是呈现给使用者的一个印象。
而且,一门语言完全可能同时用到编译执行和解释执行。比如 Java:源码先编译成字节码(中间码),运行时再由 JVM 把字节码编译或解释成机器码。所以更准确的说法是——编译执行与解释执行是编程语言的两种执行方式,而不是两门语言的全部属性。
5.6.2 编译、解释、编译器、解释器
先把四个词的定义摆清楚:
- 编译:将源代码一次性转换为机器码的过程。机器码会保存为文件,下次运行时直接运行机器码。
- 解释:将源代码逐行转换为机器码并运行的过程。机器码不会被保存下来。
- 编译执行(编译器):把一段程序直接翻译成机器码(C/C++ 这类非跨平台语言),或翻译成中间码(Java 这类跨平台语言,之后再由 JVM 把字节码编译成机器码)。编译执行会把所有语句都编译成机器语言并保存成可执行机器码,运行时直接执行机器语言,不需要再解释或编译。
- 解释执行(解释器):在程序运行时,再把中间码一行一行地解释成机器码执行,解释一行、执行一行。(例如 Java 的字节码通过 JVM 解释成机器码。)
执行编译过程的程序叫编译器,执行解释过程的程序叫解释器。
| 对比项 | 编译执行 | 解释执行 |
|---|---|---|
| 转换时机 | 程序运行之前,一次性翻译完 | 程序运行期间,边解释边执行 |
| 机器码 | 保存成可执行文件,下次直接用 | 不保存,每次运行都要重新解释 |
| 执行效率 | 高,运行时不再有翻译开销 | 相对低,翻译和执行交替进行 |
| 典型代表 | C/C++;Java 的中间码也要先编译 | Python |
5.6.3 本质区别只有一个
有一种说法是:编译型语言和解释型语言的本质都是解释执行。这两种语言之所以可以说相同,是因为它们从文本形式的源代码到最终产生结果,所经历的过程是一样的——区别只在运行时:
- 解释型语言在运行时才把程序解释成机器码来执行,机器码不保存;
- 编译型语言在运行之前,就已经让编译器把程序编译成机器码了。
这就是编译运行比解释运行更快的原因:解释型语言每次运行都要现翻译一遍,相当于把一部分时间花在了“翻译”上。
一个很贴切的比喻
编译相当于做好了一桌子菜,来了就能直接吃;解释相当于吃火锅,需要一边煮一边吃。菜都是那些菜,但吃到嘴里的效率自然不一样。
5.7 小结
这一章在 Ubuntu 里把 C++ 和 Python 的 Hello World 都跑了一遍:
- Linux 下用
gedit就能写代码,全程不离开终端; - C++ 要先装
g++、编译出a.out再运行,可执行文件后缀是.out,不像 Windows 的.exe; - Python 直接
python3运行,写起来短,但它是解释执行,速度比编译执行的 C++ 慢。
下一篇:第六章 · ROS 2 体验与系统架构。