我正在尝试使用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
答案 0 :(得分:17)
至少有两个问题。
链接器告诉您存在“未解析的外部符号”。这意味着它无法找到您尝试调用的函数的定义。在这种情况下,有两个这样的未定义函数:CreateWindowExA
和RegisterClassA
。
显然,这些函数的定义不在您的代码中,而是在Windows API库中,因此您需要通知链接器它可以在哪里找到这些定义。
SDK附带存根(*.lib
)文件,其中包含链接器使用的信息,以便它可以在运行时在Windows DLL中找到正确的函数定义。您需要指示链接器在何处可以找到这些*.lib
文件。
这样做有几种不同的策略:
简单(尽管是非可移植的)方法是在源文件中插入#pragma
语句,指示编译器保留链接器识别的注释。例如,
#pragma comment(lib, "user32")
会自动链接到user32.lib
,这是user32.dll
的存根文件。
或者,您可以将命令行上的参数传递给cl.exe
。但是,如果您没有使用MSBuild或某种make文件,这会非常复杂。在这种情况下,您需要将命令行修改为(至少):
cl test.c user32.lib
这两个选项都自然地假设您的Windows SDK目录已添加到路径中。我很确定安装程序会自动为您执行此操作,但我并不乐观。如果没有,或者您已从路径中删除这些文件,则需要在命令行上使用*.lib
文件的完全限定路径。
阅读the documentation for the possible compiler options是一个很好的起点。或者更好的是,如果您不熟悉Windows编程,请使用像Visual Studio这样的环境,将所有这些内容自动组合在一起。一旦了解了正在发生的事情,请查看Visual Studio运行的命令行,并逐位剖析。
下一个问题是你正在编译而没有定义 Unicode,并且因为ANSI is the default,Windows头文件中的所有宏都在解析为{{1}所有SDK函数的后缀版本。这可能不是你想要的。 Windows已经完全使用Unicode十多年了,所有新应用程序都应该构建为Unicode。 Unicode版本的名称后附加A
后缀。
同样,您可以通过向源文件添加行或向命令行添加参数来指示编译器使用Unicode显式构建。
在这种情况下,最简单的方法可能只是添加
W
在 #define UNICODE
之前到源文件的顶部。正如我们在上面看到的那样,在Visual Studio环境中,除非您明确地将项目设置更改为定位其他内容,否则会自动为您定义#include <windows.h>
。
答案 1 :(得分: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"