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

And*_*eKR 5 c windows winapi visual-studio

我正在尝试使用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);

[...]
Run Code Online (Sandbox Code Playgroud)

当我使用编译它时

cl test.c
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)

Cod*_*ray 18

至少有两个问题.

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

    显然,这些函数的定义不在您的代码中,而是在Windows API库中,因此您需要通知链接器它可以在哪里找到这些定义.

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

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

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

      #pragma comment(lib, "user32")
      
      Run Code Online (Sandbox Code Playgroud)

      自动链接到user32.lib,这是存根文件user32.dll.

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

      cl test.c user32.lib
      
      Run Code Online (Sandbox Code Playgroud)

    这两个选项都自然地假定您的Windows SDK目录已添加到路径中.我很确定安装程序会自动为您执行此操作,但我并不乐观.如果没有,或者您已从路径中删除这些文件,则需要*.lib在命令行上使用完全限定的文件路径.

    阅读可能的编译器选项的文档是一个很好的起点.或者更好的是,如果您不熟悉Windows编程,请使用像Visual Studio这样的环境,将所有这些内容自动组合在一起.一旦了解了正在发生的事情,请查看Visual Studio运行的命令行,并逐位剖析.

  2. 下一个问题是您在没有定义Unicode 的情况下进行编译,并且因为ANSI是默认值,所以Windows头文件中的所有宏都会解析为调用A所有SDK函数的后缀版本.这可能不是你想要的.Windows已经完全使用Unicode十多年了,所有新应用程序都应该构建为Unicode.Unicode版本W的名称后面附加了后缀.

    同样,您可以通过向源文件添加行或向命令行添加参数来指示编译器使用Unicode显式构建.

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

     #define UNICODE
    
    Run Code Online (Sandbox Code Playgroud)

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


Fre*_*red 16

这些函数存在于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"
Run Code Online (Sandbox Code Playgroud)