searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

【Qt源码笔记】万般皆是int main

2023-07-20 07:40:08
11
0

经常写 Qt 的程序,就会发现,不管是写控制台程序还是带窗体的应用程序,在 Qt 中的入口都是int main()。但实际上抛开其他平台不说,就是在 Windows 平台上,二者的入口就是有区别的。之前只是略知一点,今天翻看了一下代码,算是了解了一下。

其实这个探究过程倒也并不费劲。命令行程序暂且不表。就拿带窗体的应用程序来说,已知它的入口只能是 WinMainwWinMain_tWinMain 。不难按图索骥找到 qtmain_win.cpp 这个文件。事实上, 另一个关于 winrt 的入口定义也在同级目录下( qtbase\src\winmain )。 qtmain_win.cpp 文件内容如下:

/************************************************************************
#include "qt_windows.h"
#include "qbytearray.h"
#include "qstring.h"
#include "qvector.h"

#include <shlobj.h>

/*
  This file contains the code in the qtmain library for Windows.
  qtmain contains the Windows startup code and is required for
  linking to the Qt DLL.

  When a Windows application starts, the WinMain function is
  invoked.
*/

QT_USE_NAMESPACE


#if defined(QT_NEEDS_QMAIN)
int qMain(int, char **);
#define main qMain
#else
extern "C" int main(int, char **);
#endif

/*
  WinMain() - Initializes Windows and calls user's startup function main().
  NOTE: WinMain() won't be called if the application was linked as a "console"
  application.
*/

// Convert a wchar_t to char string, equivalent to QString::toLocal8Bit()
// when passed CP_ACP.
static inline char *wideToMulti(int codePage, const wchar_t *aw)
{
    const int required = WideCharToMultiByte(codePage, 0, aw, -1, NULL, 0, NULL, NULL);
    char *result = new char[required];
    WideCharToMultiByte(codePage, 0, aw, -1, result, required, NULL, NULL);
    return result;
}

extern "C" int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR /*cmdParamarg*/, int /* cmdShow */)
{
    int argc;
    wchar_t **argvW = CommandLineToArgvW(GetCommandLineW(), &argc);
    if (!argvW)
        return -1;
    char **argv = new char *[argc + 1];
    for (int i = 0; i < argc; ++i)
        argv[i] = wideToMulti(CP_ACP, argvW[i]);
    argv[argc] = nullptr;
    LocalFree(argvW);
    const int exitCode = main(argc, argv);
    for (int i = 0; i < argc && argv[i]; ++i)
        delete [] argv[i];
    delete [] argv;
    return exitCode;
}

这个文件中不难看出,我在自己的工程中使用的 int main() 其实就是 const int exitCode = main(argc, argv); 这一行中的 main 了。 找到了案发现场,转而想到了一个问题,这个文件是如何应用在我的工程中的。

翻看目录时候 winmain.pro 引起了我的注意,根据它的内容不难发现,这个目录在 Windows 下编译会生成 qtmain.lib 。机智的我直接去找项目工程文件( .vcxproj )。查看他的内容,一切都真相大白。在 link 部分,会发现 qtmain.lib 文件会被链接到 exe 中。而这一步的操作,应该就是 VS 中 Qt 插件的功劳了。

所以由此可推断,如果用 VS 裸写 Qt 的程序,在链接的时候除了链接必要的 Qt 库文件,还要自己手动把这个 qtmain.lib 链接进去。

0条评论
0 / 1000
Harper
17文章数
0粉丝数
Harper
17 文章 | 0 粉丝
原创

【Qt源码笔记】万般皆是int main

2023-07-20 07:40:08
11
0

经常写 Qt 的程序,就会发现,不管是写控制台程序还是带窗体的应用程序,在 Qt 中的入口都是int main()。但实际上抛开其他平台不说,就是在 Windows 平台上,二者的入口就是有区别的。之前只是略知一点,今天翻看了一下代码,算是了解了一下。

其实这个探究过程倒也并不费劲。命令行程序暂且不表。就拿带窗体的应用程序来说,已知它的入口只能是 WinMainwWinMain_tWinMain 。不难按图索骥找到 qtmain_win.cpp 这个文件。事实上, 另一个关于 winrt 的入口定义也在同级目录下( qtbase\src\winmain )。 qtmain_win.cpp 文件内容如下:

/************************************************************************
#include "qt_windows.h"
#include "qbytearray.h"
#include "qstring.h"
#include "qvector.h"

#include <shlobj.h>

/*
  This file contains the code in the qtmain library for Windows.
  qtmain contains the Windows startup code and is required for
  linking to the Qt DLL.

  When a Windows application starts, the WinMain function is
  invoked.
*/

QT_USE_NAMESPACE


#if defined(QT_NEEDS_QMAIN)
int qMain(int, char **);
#define main qMain
#else
extern "C" int main(int, char **);
#endif

/*
  WinMain() - Initializes Windows and calls user's startup function main().
  NOTE: WinMain() won't be called if the application was linked as a "console"
  application.
*/

// Convert a wchar_t to char string, equivalent to QString::toLocal8Bit()
// when passed CP_ACP.
static inline char *wideToMulti(int codePage, const wchar_t *aw)
{
    const int required = WideCharToMultiByte(codePage, 0, aw, -1, NULL, 0, NULL, NULL);
    char *result = new char[required];
    WideCharToMultiByte(codePage, 0, aw, -1, result, required, NULL, NULL);
    return result;
}

extern "C" int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR /*cmdParamarg*/, int /* cmdShow */)
{
    int argc;
    wchar_t **argvW = CommandLineToArgvW(GetCommandLineW(), &argc);
    if (!argvW)
        return -1;
    char **argv = new char *[argc + 1];
    for (int i = 0; i < argc; ++i)
        argv[i] = wideToMulti(CP_ACP, argvW[i]);
    argv[argc] = nullptr;
    LocalFree(argvW);
    const int exitCode = main(argc, argv);
    for (int i = 0; i < argc && argv[i]; ++i)
        delete [] argv[i];
    delete [] argv;
    return exitCode;
}

这个文件中不难看出,我在自己的工程中使用的 int main() 其实就是 const int exitCode = main(argc, argv); 这一行中的 main 了。 找到了案发现场,转而想到了一个问题,这个文件是如何应用在我的工程中的。

翻看目录时候 winmain.pro 引起了我的注意,根据它的内容不难发现,这个目录在 Windows 下编译会生成 qtmain.lib 。机智的我直接去找项目工程文件( .vcxproj )。查看他的内容,一切都真相大白。在 link 部分,会发现 qtmain.lib 文件会被链接到 exe 中。而这一步的操作,应该就是 VS 中 Qt 插件的功劳了。

所以由此可推断,如果用 VS 裸写 Qt 的程序,在链接的时候除了链接必要的 Qt 库文件,还要自己手动把这个 qtmain.lib 链接进去。

文章来自个人专栏
Qt 杂谈
8 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0