Skip to content

第五章 · 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,一条命令就能新建并打开文件:

bash
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,输入下面六行:

cpp
#include <iostream>
using namespace std;
int main(){
    cout<<"Hello ROS 2!"<<endl;
    return 0;
}

保存代码,关闭 gedit。

5.3.2 装编译器 ​

C++ 代码必须经过编译构建之后才能运行,而 Linux 下负责编译 C++ 的是 g++。它默认没有安装,需要手动装一下:

bash
sudo apt install g++

5.3.3 编译与运行 ​

装好之后,在终端里对刚才的源文件执行编译:

bash
g++ hello_ros2.cpp

再用 ls 看一眼当前目录,应该会多出一个叫 a.out 的文件。这个文件就是编译出来的可执行程序,直接运行它:

bash
./a.out

终端会输出 Hello ROS 2!。到这里,第一个 C++ 程序就跑通了。

Windows 的 .exe 与 Linux 的 .out

这里能看出一个明显区别:Windows 下编译出来的可执行文件是 .exe,双击就能运行;Linux 下的可执行文件是 .out(a.out 就是默认输出名),运行时必须在终端里带上 ./ 指明“运行当前目录下的这个文件”。

另外,第一次从写代码到跑起来其实敲了三行命令:装编译器、编译、运行。记住这个“三步走”,下面和 Python 对比时会用到。

5.4 第一个 Python 程序 ​

Python 这边就简单多了。同样用 gedit 新建文件:

bash
gedit hello_ros2.py

输入一行,保存并关闭:

python
print("Hello ROS 2!")

然后直接在终端里运行:

bash
python3 hello_ros2.py

Python 不需要先编译成可执行文件,也不需要额外装编译器,一行 python3 命令就能把源码跑起来。

5.5 C++ 与 Python 的直观对比 ​

把上面两段流程摆在一起看:

同一个 Hello World 在 C++ 与 Python 中的写法对比

图:Python 与 C++ 的对比

对比项C++Python
写一个 Hello World6 行(头文件、命名空间、main、输出、return、花括号)1 行
从零到跑起来3 步:装编译器、编译、运行1 步:python3 直接运行
语法风格需要声明类型、写分号、管命名空间接近自然语言
执行方式编译执行解释执行
运行速度快慢

从这张表看,Python 至少有三处占优:

  1. 程序更简单。C++ 要 6 行才能搞定的程序,Python 只要 1 行。
  2. 命令行里运行更简单。C++ 最短要三行命令,Python 只要一行。
  3. 语法更接近自然语言,读起来几乎就是一句英文。

于是有人会问:那 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 体验与系统架构。

用 VitePress 搭建 · 托管在 GitHub Pages