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 文件组成的。
简短的问题。
当我这样做时:
#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 文件组成的。