看到評論裡面有朋友抱怨以前文章裡面的例子都是 for Windows 的,沒有 for Linux 或者 for Mac 的。那麼今天就來說說跨平台的問題吧!
所謂跨平台,其實有兩種含義,一是跨硬件平台,一是跨軟件平台。對於硬件平台,很多時候我們都會不自覺的忽略掉,因為硬件差異雖然很大,但是我們能夠接觸到的卻很少。目前 PC 系列基本都是兼容的,並且編譯器可能會幫助我們完成這個問題,因此如果你的程序沒有用到匯編語言,基本很難考慮到這種跨平台的支持。但是,如果你的程序需要接觸到硬件,不管是因為功能的需要還是因為性能的需要,就不得不考慮這個問題。比如,Photoshop 的顏色處理直接使用匯編語言編寫,以達到最好性能,這就不得不考慮硬件相關的問題。通常我們說跨平台,更多的只軟件的跨平台,也就是跨操作系統。現在主流操作系統 Windows,Linux/Unix,基本算作是兩大陣營吧,它們之間的軟件都是不兼容的,所以這種跨平台是我們接觸比較多的。
說起跨平台,就不得不提 Java。這是 Java 的賣點之一:“一次編寫,到處運行”。Java 之所以能夠實現跨平台,是因為 Java 源代碼編譯成一種中間代碼,運行 Java 程序,實際上是在 JVM 中。你編寫出的 Java 程序是跨平台的,但是 JVM 不是跨平台的,必須根據你的操作系統選擇 JVM。這是適配器模式的典型應用 :-)
選擇一個本身就是跨平台的庫,你的工作量就會小很多,比如 Qt。Qt 已經幫我們封裝好很多平台相關的代碼。如果你打開一個 Qt 的源代碼,就可能找到很多關於操作系統的判斷。簡單來說,我們使用 QMainWindow::show() 就可以顯示一個窗口。在 Windows 上,Qt 必須調用 Win32 API 完成;在 Linux 上,你就可能需要調用 GNOME 或者 KDE 的 API。但是,無論如何,這部分代碼都不是我們關心的,因為 Qt 已經替我們完成了。所以,如果你的程序沒有與平台相關的代碼,那麼只需要在 Windows 上編譯成功,然後拿到 Linux 上重新編譯一下,通過一些簡單測試,或者還需要調整一下 UI 比例等等,就可以拿去發行了。
但是,如果有部分代碼不得不依賴操作系統,比如我們調用列出目錄的命令,Windows 下是 dir,而 Linux 下是 ls,這就不得不根據平台進行編譯了。這裡我們就拿這個例子嘗試一下。
mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QMainWindow>
- class QProcess;
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public:
- MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private slots:
- void openProcess();
- void readResult(int exitCode);
- private:
- QProcess *p;
- };
- #endif // MAINWINDOW_H
mainwindow.cpp
- #include <QProcess>
- #include <QPushButton>
- #include <QMessageBox>
- #include <QTextCodec>
- #include "mainwindow.h"
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- {
- p = new QProcess(this);
- QPushButton *bt = new QPushButton("display", this);
- connect(bt, SIGNAL(clicked()), this, SLOT(openProcess()));
- }
- MainWindow::~MainWindow()
- {
- }
- void MainWindow::openProcess()
- {
- #if defined(Q_OS_WIN32)
- p->start("cmd.exe", QStringList() << "/c" << "dir");
- #elif defined(Q_OS_LINUX)
- p->start("ls", QStringList() << "/home/usr_name");
- #endif
- connect(p, SIGNAL(finished(int)), this, SLOT(readResult(int)));
- }
- void MainWindow::readResult(int exitCode)
- {
- if(exitCode == 0) {
- #if defined(Q_OS_WIN32)
- QTextCodec* gbkCodec = QTextCodec::codecForName("GBK");
- QString result = gbkCodec->toUnicode(p->readAll());
- #elif defined(Q_OS_LINUX)
- QTextCodec* utfCodec = QTextCodec::codecForName("UTF-8");
- QString result = utfCodec->toUnicode(p->readAll());
- #endif
- QMessageBox::information(this, "dir", result);
- }
- }
例子和前面是一樣的,我們只是在 cpp 文件中添加了一些代碼。我們使用 #if 這些預處理指令通過判斷 Q_OS_WIN32 這樣的宏是否存在,來生成相應的平台相關的代碼。這些宏是在 Qt 中定義好的,我們只需根據它們是否存在進行判斷。這樣,我們的程序就可以在 Windows 和 Linux 下都可以編譯運行。
進行跨平台編程,你不得不需要接觸到一些平台相關的東西,比如文字符編碼等,都是需要好哈學習的。所以建議是盡可能使用 Qt 提供的標准函數進行編程,這樣就不必寫一大堆 if 判斷,代碼也更加清晰。
本文出自 “豆子空間” 博客,請務必保留此出處http://devbean.blog.51cto.com/448512/308358