如何在C4Droid中编译简单的Qt 5.2项目

How to compile simple Qt 5.2 project in C4Droid

本文关键字:Qt 2项目 简单 编译 C4Droid      更新时间:2023-10-16

我正试图弄清楚如何在C4Droid中构建和编译一个简单的Qt项目,C4Droid是一个适用于Android的C++编译器。

该程序提供了两个简单的示例:一个"Hello world"标签(一个文件)和一个示例记事本。第二个看起来很有趣,但它处理的是完全由代码创建的表单。

我正在调查是否可以使用从.ui文件生成的表单进行此操作。我在Qt Creator中为Qt 4.8创建了一个简单的项目,编译了.ui表单,并将代码从Qt 4.8改编为Qt 5.2。项目本身非常简单:一个带有QButton和QLineEdit的表单。当按下Q按钮时,QLineEdit中将显示"Hello world"。

据我所见,C4Droid不解析.pro文件。要编译项目,我必须打开main.cpp并长按"编译",选择"编译多个源代码文件(简单)",然后运行。C4droid在.cdroid文本文件中使用自己的"makefile"文件。

这些是我在C4droid测试文件夹中发布的文件:

按钮HelloWorld.pro:

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ButtonHelloWorld
TEMPLATE = app
SOURCES += main.cpp
mainwindow.cpp
HEADERS  += mainwindow.h
FORMS    += mainwindow.ui

main.cpp:

#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

主窗口.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_ButtonSayHello_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_ButtonSayHello_clicked()
{
ui->LeditSayHello->setText(tr("Hello world"));
}

ui_mainwindow.h:

#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QAction>
#include <QApplication>
#include <QButtonGroup>
#include <QHeaderView>
#include <QLineEdit>
#include <QMainWindow>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QWidget *centralWidget;
QVBoxLayout *verticalLayout;
QPushButton *ButtonSayHello;
QLineEdit *LeditSayHello;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(198, 103);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
verticalLayout = new QVBoxLayout(centralWidget);
verticalLayout->setSpacing(6);
verticalLayout->setContentsMargins(11, 11, 11, 11);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
ButtonSayHello = new QPushButton(centralWidget);
ButtonSayHello->setObjectName(QString::fromUtf8("ButtonSayHello"));
verticalLayout->addWidget(ButtonSayHello);
LeditSayHello = new QLineEdit(centralWidget);
LeditSayHello->setObjectName(QString::fromUtf8("LeditSayHello"));
LeditSayHello->setAlignment(Qt::AlignCenter);
verticalLayout->addWidget(LeditSayHello);
MainWindow->setCentralWidget(centralWidget);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0));
ButtonSayHello->setText(QApplication::translate("MainWindow", "Say Hello", 0));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H

我把原始的mainwindow.ui放在这里供参考(c4droid不使用它):

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>198</width>
<height>103</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="ButtonSayHello">
<property name="text">
<string>Say Hello</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="LeditSayHello">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

当我尝试在C4droid中从main.cpp编译这个项目时,输出是:

/storage/emulated/0/Bull/C4Droid/ButtonHelloWorld/main.cpp:0:注意:否找到相关类。未生成输出。/data/data.com/n0n3m4.droidc/files/gcc/tmpdir/ccyCC2RV.o:In函数MainWindow::MainWindow(QWidget*)': mainwindow.cpp:(.text+0xc4): undefined reference to主窗口的vtable/data/data.com/n0n3m4.droidc/files/gcc/tmpdir/ccyCC2RV.o:In函数MainWindow::~MainWindow()': mainwindow.cpp:(.text+0x14c): undefined reference to主窗口的vtable/data/data.com/n0n3m4.droidc/files/gcc/tmpdir/ccyCC2RV.o:In函数MainWindow::tr(char const*, char const*, int)': mainwindow.cpp:(.text._ZN10MainWindow2trEPKcS1_i[_ZN10MainWindow2trEPKcS1_i]+0x5c): undefined reference toMainWindow::staticMetaObject'集合2:错误:ld返回1退出状态

我能做些什么来成功编译这个项目?

当然,我在谷歌上搜索了很多,并试图将.moc文件包括在内,但没有成功。

(顺便说一句,我现在刚刚尝试创建标签"C4Droid",但我没有足够的声誉来做到这一点://)

Update1---仔细查看C4droid附带的多个文件Qt示例,我注意到它使用了Makefile。阅读Makefile时,我注意到这个文件是使用以下命令生成的:

/data/data/com.n0n3m4.droidc/files/gcc/qt/bin/qmake-spec-android-g++-o Makefile应用程序.pro

(这也让我知道moc、qmake、rcc和uic可执行文件在我的android中的/data/data/com.n0n3m4.droidc/files/gcc/qt/bin/文件夹中)

这应该根据file.pro创建一个Makefile,它会自动告诉系统在编译之前使用uic、moc等,然后进行正确的链接。所以我在我的android中输入了终端并键入:

/data/data/com.n0n3m4.droidc/files/gcc/qt/bin/qmake-spec-android-g++-o Makefile按钮HelloWorld.pro

我得到的只是:

sh:arm linux androidabi gcc:未找到

更新2

C4droid开发人员回答我:

"C4droid可以解析.pro文件,请仔细查看示例。Google Play上的描述是唯一可用的教程,但它已经足够了。">

所以我决定转到C4droid中的.pro文件。在查看了示例编译选项后,我决定长按compile,选择"Makefile"编译模式和"Qt application"运行模式,并选择"ButtonHelloWorld.qexe"作为可执行文件。

我现在编译了,一切似乎都好多了,但最后弹出了这样的消息:

复制文件失败

有什么提示吗?

更新3

好吧,我测试并玩了(很多)捆绑的Qt应用程序示例,我再次给开发人员发了电子邮件,现在它已经非常方便了。

我:

我决定用你的例子做一个测试。我已经复制到一个新文件夹(/storage/emulated/0/Bull/C4Droid/application)

images folder
application.pro
application.qrc
main.cpp
mainwindow.cpp
mainwindow.h

然后,在C4droid中,我打开application.pro,长按"编译"。选择"Makefile"编译模式和"Qt应用程序"运行模式,并将可执行文件"application.so"。它编译正常,但失败"复制文件失败"。

但如果我把"libapplication.so"作为可执行文件,它会编译并完成正常。

?为什么?

He:

因为在Android上,Qt可执行文件总是命名为libXXX.so

Me:

嗯,我尝试了"libappli.so",但得到了相同的错误。

但是,调查一下,我发现可执行文件的名称必须是lib[NameOf.proFileWithoutExtension].so,以及它的文件夹名称独立的。现在你复制的例子和我的工作!!

此外,他告诉我,一旦编译,将其导出到.APK就像菜单->导出一样简单。我试过了。。。太神奇了!!

结论

已解决。回答我自己的问题,以帮助处于同样处境的其他人。

这个答案可以被视为

在C4droid中编译和导出Qt项目的迷你教程

如何在Android的C++编译器C4Droid中构建和编译一个简单的Qt项目?

我在Qt Creator中为Qt 4.8创建了一个简单的项目,编译了.ui表单,并将代码从Qt 4.8改编为Qt 5.2。项目本身非常简单:一个带有QButton和QLineEdit的表单。当按下Q按钮时,QLineEdit中将显示"Hello world"。

这些是我在C4droid测试文件夹中发布的文件:

按钮HelloWorld.pro:

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ButtonHelloWorld
TEMPLATE = app
SOURCES += main.cpp
mainwindow.cpp
HEADERS  += mainwindow.h
FORMS    += mainwindow.ui

main.cpp:

#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

主窗口.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_ButtonSayHello_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_ButtonSayHello_clicked()
{
ui->LeditSayHello->setText(tr("Hello world"));
}

mainwindow.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>198</width>
<height>103</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="ButtonSayHello">
<property name="text">
<string>Say Hello</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="LeditSayHello">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

现在,从C4Droid打开ButtonHelloWorld.pro或main.cpp。长按Compile,选择"Makefile"编译模式和"Qt application"运行模式,并选择"libButtonHelloWorld.so"作为可执行文件。

这一点很重要:在Android Qt中,可执行文件总是命名为libXXX.so。可执行文件的名称必须是lib[NameOf.proFileWithoutExtension].so,并且它的文件夹名称是独立的。

编译和测试后,它运行正常,将其导出到.APK就像菜单->导出一样简单。

我试过了。。。太神奇了!!

PS:如果你想知道moc、qmake、rcc和uic可执行文件在哪里,它们在/data/data/com.n0n3m4.droidc/files/gcc/qt/bin/文件夹中(至少在我的android中)。

您忘记处理元对象编译器,简称"moc",用于主窗口的文件。否则,QObject机制将无法正常工作。

你需要做以下任何一件事:

moc -o mainwindow.moc mainwindow.h
g++ ... mainwindow.moc

作为构建过程的一部分,即通过显式运行moc来扩展Makefile,并将*.moc模式添加到要编译的文件列表中,或者通过它单独运行编译器命令。

或者,C4Droid似乎从3.49版本开始支持qmake项目文件。