假设我正在围绕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/