WIN32 API里的CreateFile函数如何使用绝对路径

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WIN32 API里的CreateFile函数如何使用绝对路径相关的知识,希望对你有一定的参考价值。

HANDLE CreateFile(
LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
// pointer to security attributes
DWORD dwCreationDisposition, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to
// copy
);
参数 lpFileName可以为相对路径如“aaa.txt”
但不能用绝对路径 如“c:\aaa.txt”怎么不办

参考技术A HANDLE hfile = CreateFile(_T("G:\\测试\\myfile.txt"),GENERIC_WRITE|GENERIC_READ,0
,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
如果第一个参数为_T("G:\\myfile.txt")则失败,不能直接根目录。

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

【中文标题】C头文件如何导入win32api函数?【英文标题】:How C header files import win32api functions? 【发布时间】:2020-05-04 18:16:09 【问题描述】:

简短的问题。

当我这样做时:

#include <windows.h>

CreateProcess(..)

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

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

【问题讨论】:

【参考方案1】:

标头仅包含 API 函数的声明,而不是它们的定义。通过链接适当的库可以找到定义。

例如,将以下内容复制到.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

注意编译本身实际上是成功的;抱怨缺少函数定义的是链接器。

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

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

【讨论】:

你在这里真的让我大开眼界。为什么在 gcc 中不是这样? cl.exe不能自动链接吗?另一个问题,据我了解,为了使用某个dll的功能,您需要相应的头文件,该头文件将包含所有函数签名和相关结构? @TrigosinDarom 默认情况下编译器/实现可能会隐式链接某些库,因此 GCC 可能不需要您指定 MSVC 确实需要的附加库,反之亦然。访问 DLL 的导出函数取决于您用于链接到 DLL 的方法。有关详细信息,请参阅this article on MSDN。 @TrigosinDarom 不同的 DLL 实现不同的功能,并提供单独的导入库文件来查找这些功能。您真的希望链接器了解系统上的每个 lib 文件吗?不,所以你必须告诉它你真正感兴趣的是哪个 lib 文件。因此,要静态地使用给定的 DLL 函数,您需要它的声明(头文件)和它的定义(lib 文件)。如果您要在运行时使用 GetProcAddress() 动态导入 DLL 函数,那就完全不同了(不需要 lib 文件)。【参考方案2】:

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

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

或者,您可以使用#pragma comment(lib, “XXX”) 为您执行此操作。

【讨论】:

如果你真的以某种方式指定.dll (/DELAYLOAD) 你需要GetModuleHandle GetProcAddress【参考方案3】:

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

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

大多数通用编译器/链接器工具链的项目生成文件通常会包含一组默认的 DLL 导入文件,供链接器查看,例如 kernel32.lib(可以从中解析 CreateProcess(A|W))、user32.lib 等.

【讨论】:

【参考方案4】:

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

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

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


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

【讨论】:

以上是关于WIN32 API里的CreateFile函数如何使用绝对路径的主要内容,如果未能解决你的问题,请参考以下文章

Qt 中的 Win32 API

Win32 文件封装API Demo

Win32 文件封装API Demo

Win32 API之绘图函数

UWP是否具有同步文件读/写API?

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