QGC源码分析笔记一之main.cc
前言
一切的起源来自main()函数。
正文
main.cc源码如下
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief Main executable
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QtGlobal>
#include <QApplication>
#include <QIcon>
#include <QSslSocket>
#include <QProcessEnvironment>
#include <QHostAddress>
#include <QUdpSocket>
#include <QtPlugin>
#include <QStringListModel>
#include "QGCApplication.h"
#include "AppMessages.h"
#ifndef __mobile__
#include "QGCSerialPortInfo.h"
#include "RunGuard.h"
#endif
#ifdef UNITTEST_BUILD
#include "UnitTest.h"
#endif
#ifdef QT_DEBUG
#include "CmdLineOptParser.h"
#ifdef Q_OS_WIN
#include <crtdbg.h>
#endif
#endif
#ifdef QGC_ENABLE_BLUETOOTH
#include <QtBluetooth/QBluetoothSocket>
#endif
#include <iostream>
#include "QGCMapEngine.h"
/* SDL does ugly things to main() */
#ifdef main
#undef main
#endif
#ifndef __mobile__
Q_DECLARE_METATYPE(QGCSerialPortInfo)
#endif
#ifdef Q_OS_WIN
#include <windows.h>
/// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when
/// we don't want asserts to pop a dialog on windows.
int WindowsCrtReportHook(int reportType, char* message, int* returnValue)
{
Q_UNUSED(reportType);
std::cerr << message << std::endl; // Output message to stderr
*returnValue = 0; // Don't break into debugger
return true; // We handled this fully ourselves
}
#endif
#if defined(__android__) && !defined(NO_SERIAL_LINK)
#include <jni.h>
#include "qserialport.h"
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
Q_UNUSED(reserved);
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
QSerialPort::setNativeMethods();
return JNI_VERSION_1_6;
}
#endif
/**
* @brief Starts the application
*
* @param argc Number of commandline arguments
* @param argv Commandline arguments
* @return exit code, 0 for normal exit and !=0 for error cases
*/
int main(int argc, char *argv[])
{
#ifndef __mobile__
RunGuard guard("QGroundControlRunGuardKey");
if (!guard.tryToRun()) {
return 0;
}
#endif
#ifdef Q_OS_UNIX
//Force writing to the console on UNIX/BSD devices
if (!qEnvironmentVariableIsSet("QT_LOGGING_TO_CONSOLE"))
qputenv("QT_LOGGING_TO_CONSOLE", "1");
#endif
// install the message handler
AppMessages::installHandler();
#ifdef Q_OS_MAC
#ifndef __ios__
// Prevent Apple's app nap from screwing us over
// tip: the domain can be cross-checked on the command line with <defaults domains>
QProcess::execute("defaults write org.qgroundcontrol.qgroundcontrol NSAppSleepDisabled -bool YES");
#endif
#endif
#ifdef Q_OS_WIN
// Set our own OpenGL buglist
qputenv("QT_OPENGL_BUGLIST", ":/opengl/resources/opengl/buglist.json");
// Allow for command line override of renderer
for (int i = 0; i < argc; i++) {
const QString arg(argv[i]);
if (arg == QStringLiteral("-angle")) {
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
break;
} else if (arg == QStringLiteral("-swrast")) {
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
break;
}
}
#endif
// The following calls to qRegisterMetaType are done to silence debug output which warns
// that we use these types in signals, and without calling qRegisterMetaType we can't queue
// these signals. In general we don't queue these signals, but we do what the warning says
// anyway to silence the debug output.
#ifndef NO_SERIAL_LINK
qRegisterMetaType<QSerialPort::SerialPortError>();
#endif
#ifdef QGC_ENABLE_BLUETOOTH
qRegisterMetaType<QBluetoothSocket::SocketError>();
qRegisterMetaType<QBluetoothServiceInfo>();
#endif
qRegisterMetaType<QAbstractSocket::SocketError>();
#ifndef __mobile__
qRegisterMetaType<QGCSerialPortInfo>();
#endif
// We statically link our own QtLocation plugin
#ifdef Q_OS_WIN
// In Windows, the compiler doesn't see the use of the class created by Q_IMPORT_PLUGIN
#pragma warning( disable : 4930 4101 )
#endif
Q_IMPORT_PLUGIN(QGeoServiceProviderFactoryQGC)
bool runUnitTests = false; // Run unit tests
#ifdef QT_DEBUG
// We parse a small set of command line options here prior to QGCApplication in order to handle the ones
// which need to be handled before a QApplication object is started.
bool stressUnitTests = false; // Stress test unit tests
bool quietWindowsAsserts = false; // Don't let asserts pop dialog boxes
QString unitTestOptions;
CmdLineOpt_t rgCmdLineOptions[] = {
{ "--unittest", &runUnitTests, &unitTestOptions },
{ "--unittest-stress", &stressUnitTests, &unitTestOptions },
{ "--no-windows-assert-ui", &quietWindowsAsserts, NULL },
// Add additional command line option flags here
};
ParseCmdLineOptions(argc, argv, rgCmdLineOptions, sizeof(rgCmdLineOptions)/sizeof(rgCmdLineOptions[0]), false);
if (stressUnitTests) {
runUnitTests = true;
}
if (quietWindowsAsserts) {
#ifdef Q_OS_WIN
_CrtSetReportHook(WindowsCrtReportHook);
#endif
}
#ifdef Q_OS_WIN
if (runUnitTests) {
// Don't pop up Windows Error Reporting dialog when app crashes. This prevents TeamCity from
// hanging.
DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
}
#endif
#endif // QT_DEBUG
QGCApplication* app = new QGCApplication(argc, argv, runUnitTests);
Q_CHECK_PTR(app);
#ifdef Q_OS_LINUX
QApplication::setWindowIcon(QIcon(":/res/resources/icons/qgroundcontrol.ico"));
#endif /* Q_OS_LINUX */
// There appears to be a threading issue in qRegisterMetaType which can cause it to throw a qWarning
// about duplicate type converters. This is caused by a race condition in the Qt code. Still working
// with them on tracking down the bug. For now we register the type which is giving us problems here
// while we only have the main thread. That should prevent it from hitting the race condition later
// on in the code.
qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
app->_initCommon();
//-- Initialize Cache System
getQGCMapEngine()->init();
int exitCode = 0;
#ifdef UNITTEST_BUILD
if (runUnitTests) {
for (int i=0; i < (stressUnitTests ? 20 : 1); i++) {
if (!app->_initForUnitTests()) {
return -1;
}
// Run the test
int failures = UnitTest::run(unitTestOptions);
if (failures == 0) {
qDebug() << "ALL TESTS PASSED";
exitCode = 0;
} else {
qDebug() << failures << " TESTS FAILED!";
exitCode = -failures;
break;
}
}
} else
#endif
{
if (!app->_initForNormalAppBoot()) {
return -1;
}
exitCode = app->exec();
}
app->_shutdown();
delete app;
//-- Shutdown Cache System
destroyMapEngine();
qDebug() << "After app delete";
return exitCode;
}
main.cc源码剖析如下:
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief Main executable
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QtGlobal>
#include <QApplication>
#include <QIcon>
#include <QSslSocket>
#include <QProcessEnvironment>
#include <QHostAddress>
#include <QUdpSocket>
#include <QtPlugin>
#include <QStringListModel>
#include "QGCApplication.h"
#include "AppMessages.h"
#ifndef __mobile__
#include "QGCSerialPortInfo.h"
#include "RunGuard.h"
#endif
#ifdef UNITTEST_BUILD
#include "UnitTest.h"
#endif
#ifdef QT_DEBUG
#include "CmdLineOptParser.h"
#ifdef Q_OS_WIN
#include <crtdbg.h>
#endif
#endif
#ifdef QGC_ENABLE_BLUETOOTH
#include <QtBluetooth/QBluetoothSocket>
#endif
#include <iostream>
#include "QGCMapEngine.h"
/* SDL does ugly things to main() */
#ifdef main
#undef main
#endif
#ifndef __mobile__
Q_DECLARE_METATYPE(QGCSerialPortInfo)
#endif
#ifdef Q_OS_WIN
#include <windows.h>
/// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when
/// we don't want asserts to pop a dialog on windows.
int WindowsCrtReportHook(int reportType, char* message, int* returnValue)
{
Q_UNUSED(reportType);
std::cerr << message << std::endl; // Output message to stderr
*returnValue = 0; // Don't break into debugger
return true; // We handled this fully ourselves
}
#endif
#if defined(__android__) && !defined(NO_SERIAL_LINK)
#include <jni.h>
#include "qserialport.h"
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
Q_UNUSED(reserved);
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
QSerialPort::setNativeMethods();
return JNI_VERSION_1_6;
}
#endif
[点击并拖拽以移动]
main.cc源码剖析如下:
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief Main executable
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QtGlobal>
#include <QApplication>
#include <QIcon>
#include <QSslSocket>
#include <QProcessEnvironment>
#include <QHostAddress>
#include <QUdpSocket>
#include <QtPlugin>
#include <QStringListModel>
#include "QGCApplication.h"
#include "AppMessages.h"
#ifndef __mobile__
#include "QGCSerialPortInfo.h"
#include "RunGuard.h"
#endif
#ifdef UNITTEST_BUILD
#include "UnitTest.h"
#endif
#ifdef QT_DEBUG
#include "CmdLineOptParser.h"
#ifdef Q_OS_WIN
#include <crtdbg.h>
#endif
#endif
#ifdef QGC_ENABLE_BLUETOOTH
#include <QtBluetooth/QBluetoothSocket>
#endif
#include <iostream>
#include "QGCMapEngine.h"
/* SDL does ugly things to main() */
#ifdef main
#undef main
#endif
#ifndef __mobile__
Q_DECLARE_METATYPE(QGCSerialPortInfo)
#endif
#ifdef Q_OS_WIN
#include <windows.h>
/// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when
/// we don't want asserts to pop a dialog on windows.
int WindowsCrtReportHook(int reportType, char* message, int* returnValue)
{
Q_UNUSED(reportType);
std::cerr << message << std::endl; // Output message to stderr
*returnValue = 0; // Don't break into debugger
return true; // We handled this fully ourselves
}
#endif
#if defined(__android__) && !defined(NO_SERIAL_LINK)
#include <jni.h>
#include "qserialport.h"
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
Q_UNUSED(reserved);
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
QSerialPort::setNativeMethods();
return JNI_VERSION_1_6;
}
#endif
【以上都是跨平台相关处理】
/**
* @brief Starts the application
*
* @param argc Number of commandline arguments
* @param argv Commandline arguments
* @return exit code, 0 for normal exit and !=0 for error cases
*/
【进入正题 main】
int main(int argc, char *argv[])
{
【移动平台运行互斥管理 :通过共享内存方式来进行程序互斥操作 】
【相关类如下:】
【共享内存:QSharedMemory 】
【信号量:QSystemSemaphore 】
#ifndef __mobile__
RunGuard guard("QGroundControlRunGuardKey");
if (!guard.tryToRun()) {
return 0;
}
#endif
【对于unix平台强制写入console控制台】
#ifdef Q_OS_UNIX
//Force writing to the console on UNIX/BSD devices
if (!qEnvironmentVariableIsSet("QT_LOGGING_TO_CONSOLE"))
qputenv("QT_LOGGING_TO_CONSOLE", "1");
#endif
【注册消息处理程序】
// install the message handler
AppMessages::installHandler();
【MAC系统进行的特殊命令输入 NSAppSleepDisabled相关】
#ifdef Q_OS_MAC
#ifndef __ios__
// Prevent Apple's app nap from screwing us over
// tip: the domain can be cross-checked on the command line with <defaults domains>
QProcess::execute("defaults write org.qgroundcontrol.qgroundcontrol NSAppSleepDisabled -bool YES");
#endif
#endif
【windows系统中OpenGLbuglist设置和OpenGL类型设置】
#ifdef Q_OS_WIN
// Set our own OpenGL buglist
qputenv("QT_OPENGL_BUGLIST", ":/opengl/resources/opengl/buglist.json");
// Allow for command line override of renderer
for (int i = 0; i < argc; i++) {
const QString arg(argv[i]);
if (arg == QStringLiteral("-angle")) {
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
break;
} else if (arg == QStringLiteral("-swrast")) {
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
break;
}
}
#endif
【以下是注册一些类型 枚举之类的到QML中使用】
// The following calls to qRegisterMetaType are done to silence debug output which warns
// that we use these types in signals, and without calling qRegisterMetaType we can't queue
// these signals. In general we don't queue these signals, but we do what the warning says
// anyway to silence the debug output.
#ifndef NO_SERIAL_LINK
qRegisterMetaType<QSerialPort::SerialPortError>();
#endif
#ifdef QGC_ENABLE_BLUETOOTH
qRegisterMetaType<QBluetoothSocket::SocketError>();
qRegisterMetaType<QBluetoothServiceInfo>();
#endif
qRegisterMetaType<QAbstractSocket::SocketError>();
#ifndef __mobile__
qRegisterMetaType<QGCSerialPortInfo>();
#endif
// We statically link our own QtLocation plugin
【去除windows警告 4930 4101】
#ifdef Q_OS_WIN
// In Windows, the compiler doesn't see the use of the class created by Q_IMPORT_PLUGIN
#pragma warning( disable : 4930 4101 )
#endif
【引入静态插件 QGeoServiceProviderFactoryQGC】
Q_IMPORT_PLUGIN(QGeoServiceProviderFactoryQGC)
【是否运行单元测试】
【可以学习下ParseCmdLineOptions解析arg参数】
【_CrtSetReportHook进行hook】
bool runUnitTests = false; // Run unit tests
【DEBUG模式下进行的一些参数设置】
#ifdef QT_DEBUG
// We parse a small set of command line options here prior to QGCApplication in order to handle the ones
// which need to be handled before a QApplication object is started.
bool stressUnitTests = false; // Stress test unit tests
bool quietWindowsAsserts = false; // Don't let asserts pop dialog boxes
QString unitTestOptions;
CmdLineOpt_t rgCmdLineOptions[] = {
{ "--unittest", &runUnitTests, &unitTestOptions },
{ "--unittest-stress", &stressUnitTests, &unitTestOptions },
{ "--no-windows-assert-ui", &quietWindowsAsserts, NULL },
// Add additional command line option flags here
};
ParseCmdLineOptions(argc, argv, rgCmdLineOptions, sizeof(rgCmdLineOptions)/sizeof(rgCmdLineOptions[0]), false);
if (stressUnitTests) {
runUnitTests = true;
}
if (quietWindowsAsserts) {
#ifdef Q_OS_WIN
_CrtSetReportHook(WindowsCrtReportHook);
#endif
}
#ifdef Q_OS_WIN
if (runUnitTests) {
// Don't pop up Windows Error Reporting dialog when app crashes. This prevents TeamCity from
// hanging.
DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
}
#endif
#endif // QT_DEBUG
【QGC App程序真正的入口地方 后面详谈】
【Q_CHECK_PTR宏 做了一个指针合法校验 很常用】
QGCApplication* app = new QGCApplication(argc, argv, runUnitTests); Q_CHECK_PTR(app);
【linux系统中app图标设置】
#ifdef Q_OS_LINUX
QApplication::setWindowIcon(QIcon(":/res/resources/icons/qgroundcontrol.ico"));
#endif /* Q_OS_LINUX */
【防止qRegisterMetaType注册线程抛出异常特殊操作】
// There appears to be a threading issue in qRegisterMetaType which can cause it to throw a qWarning
// about duplicate type converters. This is caused by a race condition in the Qt code. Still working
// with them on tracking down the bug. For now we register the type which is giving us problems here
// while we only have the main thread. That should prevent it from hitting the race condition later
// on in the code.
qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
【QGC app 注册C++类到QML元对象中给QML使用】
app->_initCommon();
【初始化QGC地图引擎】
【就是个全局函数: extern QGCMapEngine* getQGCMapEngine();】
//-- Initialize Cache System
getQGCMapEngine()->init();
【退出返回code定义和最上面main开头注释呼应】
int exitCode = 0;
【单元测试参数设置】
#ifdef UNITTEST_BUILD
if (runUnitTests) {
for (int i=0; i < (stressUnitTests ? 20 : 1); i++) {
if (!app->_initForUnitTests()) {
return -1;
}
// Run the test
int failures = UnitTest::run(unitTestOptions);
if (failures == 0) {
qDebug() << "ALL TESTS PASSED";
exitCode = 0;
} else {
qDebug() << failures << " TESTS FAILED!";
exitCode = -failures;
break;
}
}
} else
#endif
【_initForNormalAppBoot 初始化MainWindow主界面以及相关硬件设备 遥感之类的 最后同步Settings配置文件】
【剩下的都是些收尾工作 最后返回 exitCode】
【后续详细分析 _initForNormalAppBoot 】
【整个程序就运行起来了~】
【接下来就开始分析内部原理】
{
if (!app->_initForNormalAppBoot()) {
return -1;
}
exitCode = app->exec();
}
app->_shutdown();
delete app;
//-- Shutdown Cache System
destroyMapEngine();
qDebug() << "After app delete";
return exitCode;
}
总结
直接分析main.cc结构还是很清晰的 基本流程如下图 (省去部分配置设置)
- MSBuild的简单介绍与使用
- actionbar详解(二)
- actionbar完全解析(一)
- android galley实现画廊效果
- RavenDB:基于Windows/.NET平台的NoSQL数据库
- 神经网络算法交易:波动预测与定制损失函数
- 贝叶斯深度学习:桥接PyMC3和Lasagne构建层次神经网络
- How does it work in Mono's C# compiler?
- Cross-Origin Resource Sharing协议介绍
- 战斗民族开源神器ClickHouse:一款适合于构建量化回测研究系统的高性能列式数据库(二)
- Microsoft StreamInsight 构建物联网
- 利用 Microsoft StreamInsight 控制较大数据流
- HTML Agility Pack 搭配 ScrapySharp,彻底解除Html解析的痛苦
- 看看你是哪种级别的Python程序员(已跪)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- R语言逐步多元回归模型分析长鼻鱼密度影响因素
- R语言对回归模型进行协方差分析
- R语言多项式样条回归、非线性回归数据分析
- R语言中进行Spearman等级相关分析
- R语言相关分析和稳健线性回归分析
- R语言文本挖掘使用tf-idf描述NASA元数据的文字和关键字
- R语言对NASA元数据进行文本挖掘的主题建模分析
- 随机搜索变量选择SSVS估计贝叶斯向量自回归(BVAR)模型
- R语言VAR模型的不同类型的脉冲响应分析
- R语言用向量自回归(VAR)进行经济数据脉冲响应研究分析
- R语言从经济时间序列中用HP滤波器,小波滤波和经验模式分解等提取周期性成分分析
- python中使用scikit-learn和pandas决策树进行iris鸢尾花数据分类建模和交叉验证
- CNN+ Auto-Encoder 实现无监督Sentence Embedding ( 基于Tensorflow)
- R语言数据可视化分析案例:探索BRFSS数据
- R语言探索BRFSS数据可视化