c++ - Windows header 中是否有禁用 TCHAR 中性函数名称宏定义的设置?

标签 c++ windows

假设我正在围绕 ExpandEnvironmentStringsW 实现一个简单的包装器:

//ExpandNStuff.hpp:

#include <string>
namespace WindowsApi
{
    std::wstring ExpandEnvironmentStrings(const std::wstring& source);
}

//ExpandNStuff.cpp:

#include <windows.h>
#include "ExpandNStuff.hpp"
#include "Win32Exception.hpp"
namespace WindowsApi
{
    std::wstring ExpandEnvironmentStrings(const std::wstring& source)
    {
        DWORD len;
        std::wstring result;
        len = ::ExpandEnvironmentStringsW(source.c_str(), 0, 0);
        if (len == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }
        result.resize(len);
        len = ::ExpandEnvironmentStringsW(source.c_str(), &result[0], len);
        if (len == 0)
        {
            THROW_LAST_WINDOWS_ERROR();
        }
        result.pop_back(); //Get rid of extra null
        return result;
    }
}

没什么大不了的——到目前为止一切都有意义。看看什么时候会发生 我添加 main.cpp :

#include <iostream>
#include <string>
#include "ExpandNStuff.hpp"

int main()
{
    std::wstring source(L"Hello World! Windows is in %WINDIR%");
    std::wstring expanded(WindowsApi::ExpandEnvironmentStrings(source));
    std::wcout << expanded << std::endl;
}

惊喜!此代码不会链接。原因是在ExpandNStuff.cpp 翻译单位windows.h header 已定义 ExpandEnvironmentStrings到 是ExpandEnvironmentStringsW使用宏,尽管我们尝试过 通过将其放入命名空间来使我们的实现与众不同。所以 ExpandNStuff.cpp翻译单元认为函数被调用 WindowsApi::ExpandEnvironmentStringsW而不是 WindowsApi::ExpandEnvironmentStrings ,如作者所料。但是 main.cpp翻译单位不#include <windows.h> ,因此它的名称与 ExpandNStuff.cpp 中的名称不匹配翻译单元。

修复方法是将其添加到 ExpandNStuff.hpp 中:

#ifdef ExpandEnvironmentStrings
#undef ExpandEnvironmentStrings
#endif

但是,为每个 API 执行此操作可能会很乏味。我宁愿只是被迫显式调用函数的“W”或“A”版本,也不愿被 #define 咬住。像这样的错误。有没有办法关闭宏?

最佳答案

它们的定义没有包含在任何宏中。

WINBASEAPI
BOOL
WINAPI
GetVolumeInformationA(
    __in_opt  LPCSTR lpRootPathName,
    __out_ecount_opt(nVolumeNameSize) LPSTR lpVolumeNameBuffer,
    __in      DWORD nVolumeNameSize,
    __out_opt LPDWORD lpVolumeSerialNumber,
    __out_opt LPDWORD lpMaximumComponentLength,
    __out_opt LPDWORD lpFileSystemFlags,
    __out_ecount_opt(nFileSystemNameSize) LPSTR lpFileSystemNameBuffer,
    __in      DWORD nFileSystemNameSize
    );
WINBASEAPI
BOOL
WINAPI
GetVolumeInformationW(
    __in_opt  LPCWSTR lpRootPathName,
    __out_ecount_opt(nVolumeNameSize) LPWSTR lpVolumeNameBuffer,
    __in      DWORD nVolumeNameSize,
    __out_opt LPDWORD lpVolumeSerialNumber,
    __out_opt LPDWORD lpMaximumComponentLength,
    __out_opt LPDWORD lpFileSystemFlags,
    __out_ecount_opt(nFileSystemNameSize) LPWSTR lpFileSystemNameBuffer,
    __in      DWORD nFileSystemNameSize
    );
#ifdef UNICODE
#define GetVolumeInformation  GetVolumeInformationW
#else
#define GetVolumeInformation  GetVolumeInformationA
#endif // !UNICODE

您可以看到没有方便的开关来阻止 GetVolumeInformation 的#defining。

编辑:

Boost 有一个解决方案——BOOST_PREVENT_MACRO_SUBSTITUTION。他们将它用于 min() 和 max()。 “使用 min BOOST_PREVENT_MACRO_SUBSTITUTION (a,b); 对 min(a,b) 进行参数依赖调用。”

关于c++ - Windows header 中是否有禁用 TCHAR 中性函数名称宏定义的设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4638824/

相关文章:

具有自定义 value_type 的 C++ 映射

c++ - std::partial_sum 和 std::inclusive_scan 有什么区别?

C++:初始化列表+模板产生奇怪的错误

windows - CALL 通过时百分号消失

c++ - C++ 头文件中的大小写敏感性

c++ - 制作一个返回值的void函数

C++ STL数据结构对齐,算法向量化

python - 在 Python 中查找系统文件夹位置

python - Py2exe - 运行后窗口立即消失

windows - 使用 Win API 设置壁纸