假设我正在围绕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标头定义为ExpandEnvironmentStrings
尽管我们尝试过使用宏来ExpandEnvironmentStringsW
通过将其放在命名空间中来使我们的实现与众不同。因此
ExpandNStuff.cpp转换单元认为该函数已被调用
WindowsApi::ExpandEnvironmentStringsW而不是
正如作者所期望的那样。但是WindowsApi::ExpandEnvironmentStrings转换单元不是main.cpp,因此它的名称与#include <windows.h>转换单元中的名称不匹配。

解决方法是将此添加到ExpandNStuff.cpp中:

#ifdef ExpandEnvironmentStrings
#undef ExpandEnvironmentStrings
#endif


但是,对每个API进行此操作可能都很繁琐。我宁愿被迫显式地调用该函数的“ W”或“ A”版本,也不愿被此类的ExpandNStuff.hpp错误咬伤。有没有办法关闭宏?

最佳答案

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

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/

10-09 06:21