QT IOS链接错误,入口点(_main)未定义。

4

我目前正在尝试在IOS上编译一个基于QT的项目。我使用cmake创建和配置.xcodeproject,并使用xcode在设备上运行应用程序。

我成功地解决了所有以前的链接器错误,现在正在处理入口点。

我的main.cpp看起来像这样

    int main(int argc, char **argv) {
        QApplication app(argc, argv);
        return app.exec();
     }

这给我带来了以下错误:

错误:在调用UIApplicationMain之前创建QApplication。如果您正在编写原生iOS应用程序,并且只想部分使用Qt,则可以从UIApplication委托中的'applicationDidFinishLaunching'内部创建QApplication。

我在此帖子上发现,您应该重命名主要文件,然后qt会为您完成工作并启动应用程序生命周期

通过CMake构建的iOS上的Qt应用程序的运行时错误

Qt XCode iOS入口点

#if defined(Q_OS_IOS)
extern "C" int qtmn(int argc, char** argv) {
#else
int main(int argc, char **argv) {
#endif
    QApplication app(argc, argv);
    return app.exec();
}

但现在我正在处理这个错误

ld:找不到入口点(_main),适用于架构arm64

在第一篇帖子中,他们说我应该有一个your/qt/root/path/mkspecs/macx-ios-clang/rename_main.sh脚本

我没有得到任何东西,在另一篇帖子中,答案是:

将main重命名为qtmn(在qt源代码中),重新构建QT,并从我的main()中调用qt_main_wrapper。

但我不知道应该如何处理“重新构建并调用qt_main_wrapper”


1
我从未听说过要替换iOS的main()函数才能工作。我在iTunes Store上发布了一个应用程序,没有任何特殊处理就可以正常运行(即在iOS、Android和Win32的main()函数中不需要#ifdef)。我的main()函数看起来像这样:int main(...) { return my_singleton::run(args) }; 而我的my_singleton::run()是一个静态函数,它看起来像这样:int my_singleton::run() { singleton_ = new myQApplication(args) },其中myQApplication是QApplication的直接子类。 - markus-nm
@markus-nm 谢谢,我在这里更新了我的问题 https://forum.qt.io/topic/82102/can-t-create-qapplication-for-ios-using-cmake-build,看起来Qt没有将我的QApplication包装成ObjectiveC的等效物。 - Paltoquet
3个回答

4
修复方法是添加链接器标志。
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-Wl,-e,_qt_main_wrapper")

Qt需要一个UIApplication来进行实例化,它是UIKit中定义的应用程序。您可以在以下位置找到qt_main_wrapper的定义: qtbase/src/plugins/platforms/ios/qioseventdispatcher.mm
-e选项指定程序的另一个entryPoint,将创建此UIApplication。
如果您遵循QApplication的构造函数,将会以ios插件结束,并在“UIApplication”单例未设置时启动错误。
最后,如果您的应用程序正在使用一些QML,则...
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-u _qt_registerPlatformPlugin")

您需要在main.cpp中加载所有不同的插件。

Q_IMPORT_PLUGIN(QtQuick2Plugin)

同时,您还需要在LD Flags中添加.a文件的路径,类似于以下内容:

set (LINK_LIBRARIES ${LINK_LIBRARIES} "${USE_QT_DIR}/qml/QtQuick/Controls.2/libqtquickcontrols2plugin_debug.a")

对于QtControls2,您还需要添加以下内容

set (LINK_LIBRARIES ${LINK_LIBRARIES} "${USE_QT_DIR}/lib/libQt5QuickControls2_debug.a")
set (LINK_LIBRARIES ${LINK_LIBRARIES} "${USE_QT_DIR}/lib/libQt5QuickTemplates2_debug.a")

虽然有点麻烦,但您可以在Qt/5.7/ios/bin中运行qmlimportscanner来扫描您的项目:

qmlimportscanner -rootPath path/to/app/qml/directory -importPath path/to/qt/qml/directory

它将为您的项目提供一个JSON,其中包含所有使用的插件。 这是由qmake调用的脚本,如果我有时间,我会添加一个脚本来添加不同的插件。


太棒了!直到现在我才发现入口点重命名技巧。 - yano

0

我刚刚使用Qt 5.15.1进行了测试,现在大部分CMake iOS构建问题似乎已经得到解决。唯一剩下的是特定项目设置

set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-Wl,-e,_qt_main_wrapper")

https://bugreports.qt.io/browse/QTBUG-87060作为Qt 6的一部分发布时,这个问题也将被解决。


0
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-Wl,-e,_qt_main_wrapper")

正在使用Qt6.5

如果您正在使用qmake并遇到此错误:

错误:在调用UIApplicationMain之前,您正在创建QApplication。

请将QMAKE_LFLAGS += -Wl,-e,_qt_main_wrapper添加到您的.pro文件中,这适用于qt6.5 qt creator 10。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接