【问题标题】:How can I write a Windows application without using WinMain?如何在不使用 WinMain 的情况下编写 Windows 应用程序?
【发布时间】:2010-10-08 13:15:45
【问题描述】:

用 C/C++ 编写的 Windows GUI 应用程序将“WinMain”作为入口点(而不是“main”)。我对此的理解是编译器会生成一个由 C 运行时调用的“主”函数。这个“main”函数为 GUI 设置必要的环境并调用“WinMain”(指定实例句柄等)。

简而言之,我认为控制台和 GUI 应用程序启动在以下方面有所不同:

控制台应用程序: C 运行时 --> 'main' 函数(手工编码)

图形用户界面应用程序: C 运行时 --> 'main' 函数(编译器生成)--> 'WinMain' 函数(手工编码)

我想验证这种理解,并了解如何仅使用“main”函数(即无需编写“WinMain”)手动编写 Windows GUI。

【问题讨论】:

    标签: c winapi main crt winmain


    【解决方案1】:

    你的理解有误。 main 和 WinMain 的区别,除了一些不同的初始化代码,就是传递给它的参数。

    主要看起来像这样:

    int main(int argc, char* argv[]);
    

    而 WinMain 看起来像这样:

    int WINAPI WinMain(HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR lpCmdLine,
        int nCmdShow
    );
    

    必须设置这些参数并进行调用,这就是启动代码。当您编译和链接程序时,其中一个链接器参数是入口点,根据控制台或 GUI 应用程序的不同,这将是一段不同的启动代码。

    你当然可以自己写启动代码,只要进入你的visual c++源码目录就可以找到启动代码,它叫crt0.c,在VC\crt\src目录下。

    【讨论】:

      【解决方案2】:

      使用 Just main,您不能对 Winmain 进行编码。为说明理由,以下陈述取自 http://blogs.msdn.com/oldnewthing/archive/2007/12/03/6644060.aspx

      [在 Windows 编程中] 为什么不调用应用程序入口点 主要的?好吧,一方面,名字 main 已经被占用了,而且 Windows 无权保留备用定义。 那时还没有 C 语言标准化委员会; C是 丹尼斯说的是什么,而且很难保证丹尼斯 将采取任何特殊措施来保留 Windows 源代码 与 C 语言的任何未来版本的兼容性。自从K&R 没有指定实现可以扩展可接受的形式 的主要功能,完全有可能有一个合法的 C 编译器拒绝错误声明 main 的程序。这 当前的 C 语言标准明确允许特定于实现 main 的替代定义,但要求所有编译器都支持 这个新的 Windows 特定版本,用于编译 Windows 程序 将无偿限制您可以使用的编译器集 编写 Windows 程序。

      如果你设法克服了这个障碍,你就会遇到这样的问题 Windows 版本的 main 必须是这样的:

      int main(int argc, char *argv[], HINSTANCE hinst,
               HINSTANCE hinstPrev, int nCmdShow);
      

      由于执行 C 链接的方式,函数的所有变体都必须在 他们有共同的参数。这意味着 Windows 版本 必须将其参数添加到现有最长的末尾 主要版本,然后你必须交叉手指并希望 C 语言从未添加过 main 的另一个替代版本。如果 你走了这条路,你交叉的手指让你失望了,因为它转 一段时间后,第三个参数被添加到 main 中,它 与您的 Windows 友好版本冲突。

      假设你设法说服丹尼斯不要这样做 main 的三参数版本。你还得想出那些 前两个参数,表示每个程序的启动代码 需要包含命令行解析器。回到 16 位时代, 人们节俭地保存每个字节。告诉他们,“哦,还有你所有的 程序会变大 2KB”可能不会让你很多 的朋友。我的意思是,那是软盘上的四个 I/O 扇区!

      但可能是 Windows 入口点被赋予一个 不同的名称是为了强调这是一个不同的执行 环境。如果它被称为 main,人们会选择 C ​​程序 专为控制台环境设计,将它们放入 Windows 编译器,然后运行它们,结果是灾难性的。

      希望这能消除您的疑虑。

      【讨论】:

        【解决方案3】:

        反之亦然。编译器附带了一个静态链接的目标文件,它包含实际的入口点。该入口点进行初始化,然后调用您的入口点(即 WinMain)。

        该静态部分期望调用的内容可能是可调整的。例如,在 Visual Studio 中,链接器设置中有一个入口点名称字段。

        【讨论】:

        • 那么控制台和GUI应用案例的执行顺序是怎样的呢?在这两种情况下,静态部分是否不同? C 运行时适用于何处?
        • 首先执行静态部分,然后调用用户实现的入口点。它可以不同也可以相同,但链接器可以根据设置将调用链接到不同的入口点。您可以将此静态部分视为 C 运行时的一部分。
        猜你喜欢
        • 2015-08-17
        • 2010-11-04
        • 2015-10-13
        • 1970-01-01
        • 2016-02-02
        • 1970-01-01
        • 1970-01-01
        • 2017-11-22
        • 1970-01-01
        相关资源
        最近更新 更多