【问题标题】:How do I properly call the CopyFile function in Visual C++?如何在 Visual C++ 中正确调用 CopyFile 函数?
【发布时间】:2013-03-17 06:51:23
【问题描述】:

我有一个函数,它需要两个 CHAR* 作为输入即。 int _stdcall FileTrans(char* InFile, char* OutFile) 在 DLL 项目中。

在函数中,我只是在经过一些处理(与文件无关)之后调用CopyFile(InFile, OutFile, false);。但它说它需要两个输入作为LPCWSTR。我用谷歌搜索了它,但找不到任何有趣的东西。

【问题讨论】:

    标签: c++ string winapi visual-c++


    【解决方案1】:

    与所有接受字符串参数的 Windows API 函数一样,CopyFile 函数实际上有两种变体:

    • CopyFileA 是 ANSI 版本,它采用系统默认字符集中的 narrow(非 Unicode)字符串。基本上,它接受 const char* 类型的参数,但 Windows 标头为此使用 typedef LPCSTR

    • CopyFileW 是宽版本,它采用 Unicode 字符串。为此,它接受w_char* 类型的参数,但Windows 标头为此使用typedef LPCWSTR(注意typedef 中的附加W)。

    然后,根据是否为您的项目定义了 UNICODE 预处理器宏(在包含 Windows 标头之前的代码中,或在 Visual Studio 中的项目属性中),Windows 标头将未修饰的 CopyFile 定义为CopyFileA 或 CopyFileW。自然,如果定义了UNICODE,CopyFile 将被定义为Unicode 版本的CopyFileW。否则,它将被定义为 CopyFileA。这个想法是对通用 CopyFile 函数的调用在编译时自动解析为正确的变体。

    当然,既然您了解了所有这些,您几乎可以忘记它。在现代 Windows 编程中,完全没有理由调用旧 ANSI 版本的函数或处理窄字符串。忘记char* 甚至可以用作字符串类型——那些字符串对你来说已经死了。从现在开始,您将要使用的唯一字符串是 Unicode 字符串,由 wchar_t 字符组成。因此,UNICODE 符号应该始终为您的代码定义,并且您应该只使用W 版本的 Windows API 函数。

    再次查看 CopyFileW 函数的原型(与定义 UNICODE 调用 CopyFile 时得到的相同),我们看到:

    BOOL WINAPI CopyFile(LPCWSTR lpExistingFileName,
                         LPCWSTR lpNewFileName,
                         BOOL bFailIfExists);
    

    回想一下,您在上面了解到LPCWSTR 只是 const wchar_t* 的 typedef 同义词,const wchar_t* 是由宽字符组成的 C 样式字符串。您已经知道为什么参数标记为const:因为该函数不会修改这些值。

    并且因为您在上面也了解到这些是您应该再使用的唯一类型的字符串,下一步是修改您的 FileTrans 函数以接受宽字符串(如果不打算修改,则将它们设为 const他们):

    int _stdcall FileTrans(const wchar_t* InFile, const wchar_t* OutFile);
    

    现在,在 FileTrans 内部,您可以毫无问题地调用 CopyFile,因为您拥有正确的字符串类型。


    但有一点免费的额外建议:永远不要在 C++ 中使用原始 C 风格的字符串。始终使用由 <string> 标头在 std 命名空间中定义的 C++ 字符串类。

    这个类有两个常见的变体,std::stringstd::wstring。和以前一样,w 指的是宽字符串,这是您想在 Windows 中使用的唯一类型。所以std::wstring 是您在整个代码库中对CHAR* 的新替代品。

    将 FileTrans 函数的声明更改为如下所示:

    #include <string>
    
    // ...some other stuff...
    
    int __stdcall FileTrans(const std::wstring& InFile, const std::wstring& OutFile);
    

    请注意,我已将您原来的 CHAR* 参数更改为对 std::wstring 对象的常量引用。常量引用在这里工作得很好,因为您不会在函数内部更改其中任何一个值。

    如果您不清楚常量的含义、如何使用引用或类类型在 C++ 中的一般工作方式,请咨询您的favorite C++ book)——这是所有 C++ 程序员都需要的知识。请记住,C++ 与 C 语言不同,因此不适用相同的习语。在许多情况下,有更好的方法来做事,这当然是这种情况的一个例子。

    【讨论】:

    • 另一方面,如果将代码更改为使用基于wchar_t 的值而不是基于char 的值不是一种选择,那么只需将调用更改为CopyFile() 以使用@ 987654353@ 直接代替,因为它需要char* 作为输入。
    猜你喜欢
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多