栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

一起自学SLAM算法:2.2 C++代码编译方法

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一起自学SLAM算法:2.2 C++代码编译方法

连载文章,长期更新,欢迎关注:


写在前面

第1章-ROS入门必备知识

第2章-C++编程范式

        2.1 C++工程组织结构

        2.2 C++代码编译方法

        2.3 C++编程风格指南

...

更多精彩内容,持续更新中......


大家如有任何技术问题,欢迎加入QQ技术群(117698356),进群一起交流讨论

本书使用Linux系统进行代码开发,所以这里讨论一下C++代码在Linux中的编译方法。由于本书需要用到ROS框架,因此将在Ubuntu系统中讲解具体案例,如果还没有安装Ubuntu系统的朋友,可以参考附录部分的内容自行安装。

这里以一个简单的C++工程为例,分别讲解g++、make和CMake三种编译工具的用法。首先来构建这个C++工程,新建一个文件夹demo,在demo中新建三个文件分别命名main.cpp、foo.h和foo.cpp。首先是foo.h,在里面声明类,内容见代码清单2-1。

代码清单2-1  foo.h文件内容

 1 #ifndef FOO_H_
 2 #define FOO_H_
 3 
 4 #include 
 5 
 6 namespace foo
 7 {
 8     class MyPrint
 9     {
10     public:
11         MyPrint(std::string output);
12         void ExcutePrint();
13 
14         std::string output_;
15     };
16 }
17 #endif

第1、2和17行,是宏定义,防止头

文件的重复包含与编译。

第6行,是命名空间设置,防止出现重复的函数和变量名称。命名空间在C++中使用很普遍,而且能提高代码的可阅读性。

第8~15行,声明类,这里并不对类的的函数做具体实现,函数的具体定义将放在对应的*.cpp文件中。其中第11行,是构造函数,带一个字符串类型的参数。第12行,是执行打印的成员函数。

第14行,是存储打印内容的成员变量。

然后是foo.cpp,在里面对类的函数做具体实现,内容见代码清单2-2。

代码清单2-2  foo.cpp文件内容

 1 #include "foo.h"
 2 #include 
 3 #include 
 4 
 5 namespace foo
 6 {
 7     MyPrint::MyPrint(std::string output):output_(output)
 8     {
 9         std::cout<<"class MyPrint created a object!";
10         std::cout< 

第1行,配套的头文件必须包含。

第7~11行,构造函数的具体实现,函数头部需要使用类名作为作用域,函数的传参用来给类成员变量output_赋值,函数体内执行打印信息,表示该类已经被实例化。

第13~16行,执行打印的函数的具体实现。

最后是main.cpp,在里面对类进行实例化,并调用类中的成员函数实现打印,内容见代码清单2-3。

代码清单2-3  main.cpp文件内容

1 #include "foo.h"
2 
3 int main(int argc, char** argv)
4 {
5     foo::MyPrint my_print("I can output string!");
6     my_print.ExcutePrint();
7     return 0;
8 }

第1行,包含该头文件,以便使用里面的类MyPrint。

第5行,创建类MyPrint的实例对象,并传入初始化参数。

第6行,调用对象中的成员函数,执行打印操作。

2.2.1 使用g++编译代码

在Linux系统中,采用g++编译C++代码是最直接的方式。编译过程分成4步,分别是预处理、编译、汇编和连接,编译过程如图2-3所示。

 图2-3  g++编译过程

在了解完g++的编译过程之后,就可以用g++对上面新建的C++工程进行编译了。先安装一下g++工具,打开命令行终端,输入如下命令。

sudo apt install g++ 

安装好g++后,就可以对demo工程进行编译了,编译命令如下。

cd demo/
g++ foo.cpp main.cpp -o demo

上面的编译命令执行后,将对foo.cpp和main.cpp进行编译,最后生成可执行文件demo,直接用下面的命令便可以运行可执行文件demo。

./demo
2.2.2 使用make编译代码

当程序非常庞大时会涉及很多个*.cpp和外部依赖库,再去一个个敲g++的命令将很不方便。这时候就可以使用makefile文件来编写编译脚本,然后使用make命令进行编译。

将上面的编译命令改写成makefile的形式,在文件夹demo中新建一个文件makefile,文件内容如代码清单2-4所示。

代码清单2-4  makefile文件内容

1 start:
2     g++ -o foo.o -c foo.cpp
3     g++ -o main.o -c main.cpp
4     g++ -o demo foo.o main.o
5 clean:
6     rm -rf foo.o main.o

第1和5行,是命令块的命名,makefile中的命令可以划分成不同的块,默认make命令是调用第一个块的命令。make命令后面接命令块的名称,可以调用相应块的命令。

第2~4行,分别对各个*.cpp文件进行编译,最后将生成的目标文件*.o连接得到可执行文件demo。这里要注意,命令前面必须使用tab进行缩进。

第6行,删除编程产生的中间文件,从这里可以看出makefile中的命令是完全兼容Linux命令的。

在命令行终端用make命令编译试试。

cd demo/
make

编译完成后,目录下会生成一些中间文件,用make clean命令清除这些中间文件。

make clean 

清除完中间文件后,就只剩下可执行文件demo了,直接用下面的命令便可以运行可执行文件demo。

./demo
2.2.3 使用CMake编译代码

虽然makefile已经大大降低了大型程序的编译难度,但是程序的的众多依赖和关联,如果全部手动去维护这些依赖关系还是很麻烦的。CMake可以自动处理程序之间的关系,并产生对应的makefile文件,然后调用make就能轻松编译了。

将上面的编译改成CMake的方式,在文件夹demo中新建一个文件CMakeLists.txt,文件内容如代码清单2-5所示。

代码清单2-5  CMakeLists.txt文件内容

1 cmake_minimum_required (VERSION 2.8)
2 project(demo)
3 
4 include_directories("${PROJECT_BINARY_DIR}")
5 
6 add_library(foo foo.cpp)
7 add_executable (demo main.cpp)
8 target_link_libraries (demo foo)

第1行,声明CMake最低要求的版本。

第2行,声明CMake的工程名。

第4行,设置头文件搜索路径。

第6行,创建库文件。

第7行,创建可执行文件。

第8行,为可执行文件连接依赖库。

在命令行终端用CMake命令编译试试,命令执行后,目录下会产生大量的中间文件和一个Makefile文件。继续用make命令编译,就可以得到可执行文件demo。

cd demo/
cmake .
make

编译完成后,直接用下面的命令便可以运行可执行文件demo。

./demo

文件CMakeLists.txt的编写需要遵循CMake的语法,想要了解更多CMake语法的细节,可以访问CMake的wiki页面。

其实不难发现,第1章中讲过的ROS功能包,也是采用CMake方式编译的,只不过ROS对CMake做了进一步的封装,即catkin_make。

参考文献

【1】 张虎,机器人SLAM导航核心技术与实战[M]. 机械工业出版社,2022.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1008393.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号