如何使用cl编译Window API程序?

我正在尝试使用Windows SDK命令提示编译一个简单的C Windows API程序。

这里节目的摘录:

#include <Windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { [...] RegisterClass(&wc); hwnd = CreateWindow("test", NULL, 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); [...] 

当我编译使用

 cl test.c 

在Windows SDK Command Promt中,它给了我很多像这样的链接器错误:

 test.obj : error LNK2019: unresolved external symbol __imp_CreateWindowExA referenced in function WinMain test.obj : error LNK2019: unresolved external symbol __imp_RegisterClassA referenced in function WinMain 

Solutions Collecting From Web of "如何使用cl编译Window API程序?"

这些函数存在于user32.lib中。 您需要将其提供给cl工具。

 cl test.c ""C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\user32.lib" Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.307 Copyright (C) Microsoft Corporation. All rights reserved. test.c Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:test.exe test.obj "C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\user32.lib" 

至少有两个问题。

  1. 链接器告诉你,有一个“无法解析的外部符号”。 这意味着它无法找到您试图调用的函数的定义。 在这种情况下,有两个这样的未定义函数: CreateWindowExARegisterClassA

    很显然,这些函数的定义不是在你的代码中找到,而是在Windows API库中,所以你需要通知链接器在哪里可以找到这些定义。

    SDK带有存根( *.lib )文件,其中包含链接器使用的信息,以便它可以在运行时在Windows DLL中找到正确的函数定义。 您需要指示链接器在哪里可以找到这些*.lib文件。

    有几种不同的策略可以这样做:

    1. 简单(尽管不可移植)的方法是在源文件中插入一个#pragma语句,指示编译器留下链接器识别的注释。 例如,

       #pragma comment(lib, "user32") 

      自动链接到user32.lib ,它是user32.dll的存根文件。

    2. 或者,您可以将命令行上的参数传递给cl.exe 。 但是,如果你不使用MSBuild或者某种make文件,这个变得非常复杂。 在这种情况下,您需要修改您的命令行(至少):

       cl test.c user32.lib 

    这两个选项自然会假定您的Windows SDK目录已添加到路径中。 我很确定安装程序自动为你做,但我不积极。 如果没有,或者从路径中删除了这些文件,则需要在命令行上使用完全限定的路径指向*.lib文件。

    阅读可能的编译器选项的文档是一个很好的开始。 或者更好的是,如果您不熟悉Windows编程,则可以使用像Visual Studio这样的环境自动将所有这些东西放在一起 。 一旦你明白了发生了什么,看看Visual Studio运行的是什么命令行,然后逐位分解。

  2. 接下来的问题是你编译时没有定义Unicode,并且因为ANSI是默认的 ,所以Windows头文件中的所有宏都解析为调用所有SDK函数的后缀版本。 这可能不是你想要的。 现在Windows已经完全使用了十多年了,所有的新应用程序都应该被构建为Unicode。 Unicode版本的名称附有W后缀。

    同样,您可以指示编译器使用Unicode进行显式编译,方法是将源代码行添加到源文件中,或将参数添加到命令行中。

    在这种情况下,最简单的方法可能只是添加

      #define UNICODE 

    #include <windows.h> 之前的源文件的顶部。 正如我们上面看到的,从Visual Studio环境中, UNICODE会自动为您定义,除非您明确地将项目设置更改为其他目标。