C头文件如何导入win32api函数?

How C header files import win32api functions?

简短的问题。

当我这样做时:

#include <windows.h>

CreateProcess(..)

头文件如何知道将我连接到正确的 dll?

这些头文件中是否有字典将每个 win32api 函数映射到相关的 dll?

简短回答:头文件不知道实现这些功能的 DLL。

通常,您会将这些 DLL 指定给链接器。

或者,您可以使用 #pragma comment(lib, “XXX”) 为您完成。

头文件不知道也不关心函数的位置。头文件只是声明函数。当您在代码中调用函数时,编译器只会在目标文件中发出引用,以记录正在调用的函数。

编译器完成后,链接器会将所有目标文件放在一起并更新函数引用以指向实际实现,无论它们是否位于 DLL 中。因此,您必须向链接器(而不是编译器)提供必要的信息,它需要知道哪些目标文件和 DLL 导入文件可以查看函数的位置。

大多数通用 compiler/linker 工具链的项目 makefile 通常包含一组默认的 DLL 导入文件供链接器查看,例如 kernel32.lib(其中 CreateProcess(A|W) 可以解析来自), user32.lib, 等等

headers 只包含 API 函数的声明,不包含它们的定义。通过 linking 相应的库可以找到这些定义。

例如,将以下内容复制到 .c 文件中:

#include <Windows.h>

int main()
{
    MessageBoxW(NULL, L"Hello World", L"", MB_OK);
    return 0;
}

尝试在 Visual Studio 命令提示符下使用命令 cl example.c 编译它。您将看到错误消息:

example.obj : error LNK2019: unresolved external symbol __imp__MessageBoxW@16 referenced in function _main

请注意,编译本身实际上是成功的; linker 抱怨缺少函数定义。

如果您改为使用 cl example.c /link user32.lib 编译它,link 用户将找到 MessageBox 的定义。你也可以 link example.obj user32.lib.

因此,回答您的问题:headers 不需要知道函数在哪些 DLL 中,因为项目需要提供适当的库引用。幸运的是,Windows API 函数的 MSDN 文档会告诉您该函数在哪个 DLL 中以及哪个库 link.

为了静态 link 到 DLL(是的,静态),您 link 针对声明要导入的函数的 .lib 库。

VS 编译器支持一个#pragma,告诉linker 使用某个.lib 文件(使用特定的路径解析规则)。这样的 #pragma 存在于 Windows 头文件中。

现在在加载时,系统使用特定的路径解析规则查找.lib文件中命名的DLL文件,并将导入的原型与DLL导出的函数进行匹配。


因此,将函数映射到 DLL 的字典实际上是由每个 DLL 的头文件引用的 .lib 文件组成的。