书写一个Hello SLAM程序
创建一个slam文件,打开终端,创建c++文件,首先安装g++
sudo apt-get install g++
创建名为helloslam.c的文件
touch helloslam.cpp
进入文件进行编辑(ESC退出编辑模式,输入:wq 保存退出)
vim helloslam.cpp
//slambook2/ch2/helloslam.cpp
#include <iostream>
using namespace std;
int main(int argc, char **argv){
cout << "Hello SLAM!" <<endl;
return 0;
}
对文件进行编译
g++ helloslam.cpp
文件中生成a.out文件,而且具有执行权限,运行此程序
./a.out
程序输出Hello SLAM!
使用cmake
理论上,任意一个C++程序都可以用g++来编译。但对于太复杂的C++程序,g++命令需要大量的编译指令,且整个编译过程会变得异常繁琐。cmake在工程上广泛使用。
在一个cmake工程中,我们会用cmake命令生成一个makefile文件,然后,用make命令根据这个makefile文件的内容编译整个工程。
新建一个 CmakeLists.txt文件
touch CmakeLists.txt
编译CmakeLists文件
vim CmakeLists.txt
以下为 CmakeLists.txt的内容
# slambook2/ch2/CmakeLists.txt
# 声明要求的cmake最低版本
cmake_minimum_required( VERSION 2.8 )
# 声明一个cmake工程
project( HelloSLAM )
#添加一个可执行程序
#语法:add_executable ( 程序名 源代码文件)
add_executable( helloSLAM helloSLAM.cpp )
在当前目录下,调用cmake对该工程进行cmake编译:
cmake .
cmake会输出一些编译信息,然后在当前目录下生成一些中间文件,其中最重要的就是MakeFile。由于MakeFile是自动生成的,所以不需要修改。然后用make命令对工程进行编译:
make
在编译过程中会输出一个编译进度。如果顺利通过,我们就可以得到在CMakeLists.txt中声明的那个可执行程序helloSLAM。执行它:
./helloSLAM
这次我们使用了先执行cmake再执行make的做法,执行cmake的过程处理了工程文件之间的关系。而执行make过程实际调用了g++来编译程序。虽然这个过程中多了调用cmake和make的步骤,但我们对项目的编译管理工作,从输入一串g++命令,变成了维护若干了比较直观的CMakeLists.txt文件,这将明显降低维护整个工程难度。
如果想新增一个可执行文件,只需要在CMakeLists.txt中添加一行“add_executable”命令即可,而后续的步骤是不变的。cmake会帮我们解决代码的依赖关系,无须输入一大串g++命令。
上一种方法中,cmake生成的中间文件还留在我们的代码文件中。一种更好的方法是让这些中间文件放在一个中间目录中,在编译成功后,把这个中间目录删除即可。更常见的编译cmake工程的做法如下:
mkdir build
cd build
cmake ..
make
使用库
在一个C++工程中,并不是所有的代码都会编译成可执行文件。只有带main函数的文件才会生成可执行程序。而另一些代码,我们只想把它们打包成一个东西,供其他程序调用。这个东西叫做库(Library)。
OpenCV库提供了许多计算机视觉相关的算法;Eigen库提供了矩阵代数的计算。
首先,使用cmake生成库,并且使用库中的函数。
新建一个libHelloSLAM.cpp文件
//slambook2/ch2/libHelloSLAM.cpp
//这是一个库文件
#include <iostream>
using namespace std;
void printHello(){
cout << "Hello slam " << endl;
这个库提供了一个print函数,调用此函数将输出一条信息,但是没有main函数,这意味着这个库中没有可执行文件。在CMakeLists.txt里加上如下内容:
# slambook2/ch2/CmakeLists.txt
add_library( hello_shared SHARED libHelloSLAM.cpp )
这条命令告诉cmake,我们想把这个文件编译成一个叫做“hello”的库,然后用cmake编译整个工程。
cd build
cmake ..
make
此时得到的是共享库,得到libhello_shared.so。在Linux中,库文件分成静态库和共享库两种。静态库以.a作为后缀名(在文件中加入add_library( hello libHelloSLAM.cpp )),共享库以.so结尾。所有库都是一些函数打包的集合,差别在于静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间。
库文件是一个压缩包,里面有编译好的二进制函数,如果仅有.a或.so库文件,那么我们并不知道里面的函数是什么,调用的形式又是什么样的。为了让别人(或者自己)使用这个库,我们需要提供一个头文件,说明这个库有什么,因此,对于库的使用者,只要拿到了头文件和库文件,就可以调用这个库。
新建一个libhello的头文件。
//slambook2/ch2/libHelloSLAM.h
#ifndef LIBHELLOSLAM_H_
#define LIBHELLOSLAM_H_
//上面的宏定义是为了防止重复引用这个头文件而引起的重定义错误
//打印一句Hello的函数
void printHello();
#endif
根据这个文件和刚才编译得到的库文件,就可以使用printHello函数了。最后,使用这样一个可执行程序来调用这个简单的函数:
//slambook2/ch2/useHello.cpp
#include "libHelloSLAM.h"
// 使用libHelloSLAM.h中的printhello()函数
int main(imt argc,char **argv){
printHello();
return 0;
}
在CMakeLIsts.txt中添加一个可执行程序的生成命令,链接到刚才使用的库上。
//slambook2/ch2/CMakeLists.txt
add_executable( useHello useHello.cpp )
target_link_libraries( useHello hello_shared )
然后进行编译
cmake ..
make
运行文件
./useHello